home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
v10n04.arc
/
MBOOT.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-02-01
|
174KB
|
5,232 lines
PAGE ,132
;============================================================================
; MultiBoot - A program to allow PC Compatibles to have multiple
; boot sequences.
;
; Release history:
;
; 1.0 Initial Release PC Magazine Vol. 10, Num 4
;
;============================================================================
ROOT_DIR equ 2400h ;Offset in of root dir
DATA_SEG1 equ 1790h ;Holds IO.SYS data on copy
DATA_SEG2 equ 2790h ;Holds MSDOS.SYS data on copy
FAT_SEGMENT1 equ 3790h ;Holds 1st 64K of FAT
FAT_SEGMENT2 equ 4790h ;Holds 2nd 64K of FAT
NAME_LENGTH equ 20 ;Length of session name
DTA_OFFSET equ 80h
SYSFILE_ATTR equ 07h ;Hidden, system, read only.
NEXT_ENTRY equ offset name2 - offset name1
AUTO_OFFSET equ offset auto1 - offset name1
CONFIG_OFFSET equ offset config1 - offset name1
OSTYPE_OFFSET equ offset ostype1 - offset name1
NEXT_OSENTRY equ offset os_name2 - offset opsys_table
OPSYS_TYPE equ offset os_boottype - offset opsys_table
MENU_SELECTED equ offset selected - offset menu_struc
MENU_PROMPT equ offset prompt_loc - offset menu_struc
MENU_TIMEOUT equ offset timeout - offset menu_struc
MENU_FIRSTITEM equ offset firstitem - offset menu_struc
COLOR_NORM equ 17h ;Video attributes used for
COLOR_HIGH equ 71h ; menus.
BW_NORM equ 07h
BW_HIGH equ 70h
partition_ptrl equ word ptr [bp-60]
partition_ptrh equ word ptr [bp-58]
boot_disk equ byte ptr [bp-56]
sectors2read equ byte ptr [bp-55]
fat_sectorl equ word ptr [bp-54]
fat_sectorh equ word ptr [bp-52]
root_sectorl equ word ptr [bp-50]
root_sectorh equ word ptr [bp-48]
root_bytes equ word ptr [bp-46]
data_startl equ word ptr [bp-44]
data_starth equ word ptr [bp-42]
read_buff equ word ptr [bp-36]
old_choice equ word ptr [bp-34]
bytes_per_clust equ word ptr [bp-30]
new_io_size equ word ptr [bp-24]
new_dos_size equ word ptr [bp-22]
low_fat_size equ word ptr [bp-20]
hi_fat_size equ word ptr [bp-18]
bytes_per_sec equ word ptr [bp+0bh]
sec_per_cluster equ byte ptr [bp+0dh]
reserved_sec equ word ptr [bp+0eh]
number_of_fats equ byte ptr [bp+10h]
root_size equ word ptr [bp+11h]
total_sec equ word ptr [bp+13h]
media_des_byte equ byte ptr [bp+15h]
sec_per_fat equ word ptr [bp+16h]
sec_per_track equ word ptr [bp+18h]
number_of_heads equ word ptr [bp+1ah]
num_hidden_sec equ word ptr [bp+1ch]
total_sec_long equ word ptr [bp+20h]
drive_number equ word ptr [bp+24h]
reserved equ word ptr [bp+25h]
extended_flag equ word ptr [bp+26h]
vol_serial equ word ptr [bp+27h]
vol_name equ word ptr [bp+2bh]
;============================================================================
; MBOOT - A substitute boot record to allow PC Compatibles to have
; multiple boot sequences.
;
; ***********************
; !!!! WARNING !!!!
; ***********************
;
; Tampering with this source code can cause boot failures, lost data,
; and sad times. Be smart, just say no.
;
;============================================================================
code segment
assume cs:code
org 100h
entry: jmp main
ooem_name db 8 dup (" ") ;These values will be modified
obytes_per_sec dw ? ; by the install routine.
osec_per_cluster db ?
oreserved_sec dw ?
onumber_of_fats db ?
oroot_size dw ?
ototal_sec dw ?
omedia_des_byte db ?
osec_per_fat dw ?
osec_per_track dw ?
onumber_of_heads dw ?
onum_hidden_sec dw ? ;Added in DOS 3.x
dw ?
ototal_sec_long dd ? ;Added in DOS 4.x
odrive_number db ?
oreserved db ?
oextended_flag db ?
ovol_serial dd ?
ovol_name db 11 dup (?)
oreserved1 db 8 dup (?)
;-----------------------------------------------------------------------
; Start of boot code
;-----------------------------------------------------------------------
bootcode proc near
assume ds:code
cli ;Disable interrupts
cld ;Set direction UP.
xor bx,bx
mov ax,790h
mov ss,ax ;SS:SP = 790:0
mov sp,bx
sti ;Interrupts OK
mov bp,100h ;Set up BP for data addressing
mov partition_ptrl,si ;Save partition table ptr
mov ds,bx ;DS = 0
mov es,ax ;ES = 790h
mov di,bp ;Move boot code out of the way
mov si,7c00h
mov cx,256
rep movsw
push es
mov ax,offset boot_1
push ax
retf
boot_1:
push cs
pop ds ;DS = 790h
mov boot_disk,dl ;Save boot_disk
mov ax,bx ;BX = 0
mov al,number_of_fats ;Compute the sector of the
mul sec_per_fat ; root directory.
mov cx,reserved_sec
add cx,num_hidden_sec
adc dx,num_hidden_sec[2]
mov fat_sectorl,cx
mov fat_sectorh,dx
add cx,ax
adc dx,bx ;BX = 0
mov root_sectorl,cx
mov root_sectorh,dx
mov data_startl,cx
mov data_starth,dx
push dx
mov ax,32 ;Get length of dir entry
mul root_size ;Compute the size -in sectors-
mov si,bytes_per_sec ; of the Root Directory.
add ax,si
dec ax
div si
add data_startl,ax
adc data_starth,bx
mov root_bytes,ax ;Save size of root dir
xchg ax,cx
pop dx
mov bx,ROOT_DIR
call read_disk
jc boot_error
mov si,offset mboot_name
call load_and_boot
call print_line ;Print lost MBOOT.SYS msg
mov si,offset lastboot_name ;If fail, try old boot record
call load_and_boot
boot_error:
push si
mov si,offset bootfail_msg
call print_line
pop si
call print_line
boot_halt: jmp short boot_halt
bootcode endp
;-----------------------------------------------------------------------
; Read disk / Write Disk
; Entry: DX,AX - Absolute sector to read/write
; BX - address of buffer.
; CL - Number of sectors to read
; Exit: CF - Clear if read successful.
;-----------------------------------------------------------------------
write_disk proc near
mov ch,3 ;BIOS write disk
jmp short read_0
write_disk endp
read_disk proc near
mov ch,2 ;BIOS read disk
read_0:
push di
mov sectors2read,cl ;Save number of sectors to read
mov si,ax ;Save starting sector to read
mov di,dx
mov read_buff,bx
read_1:
;Compute the Cylinder, Head, and Sector to read.
mov ax,si ;Get logical sector
mov dx,di
mov bx,sec_per_track ;Get sectors per track
div bx
inc dx
inc bx
cmp cl,4 ;Never read more than 4
jb read_2 ; sectors
mov cl,4
read_2:
push dx
add dl,cl ;Prevent a disk read across
cmp dx,bx ; a track boundry.
pop dx
jbe read_21
dec cl
jmp short read_2
read_21:
mov bx,dx ;Save sector
push cx ;Save sectors to read
cwd
div number_of_heads ;Compute head and cylinder
xchg ah,al ;Swap cyl low and high bytes
mov cl,6
shl al,cl ;Shift high cyl bits
xchg cx,ax ;Copy cyl into CX
or cl,bl ;Combine cyl with sector
mov dh,dl ;Move head number
pop ax
mov bh,5 ;Try to read 5 times.
read_3:
push bx
push ax
mov bx,read_buff
mov dl,boot_disk ;Get disk to read
push ax ;Save sectors read
int 13h ;Read/Write disk.
pop ax ;Get sectors read
xor ah,ah
jc read_4 ;Error, try again.
pop cx ;Restore read/write cmd
pop bx ;Restore retry count
add si,ax ;Update starting sector
adc di,0
sub sectors2read,al ;Sub from total sectors to read
mul bytes_per_sec ;Move read buffer pointer
add read_buff,ax
mov cl,sectors2read
cmp cl,0
ja read_1
clc
read_exit:
pop di
ret
read_4:
xor ax,ax ;Reset disk before reading
int 13h
pop ax
pop bx
dec bh
jnz read_3
mov si,offset readerr_msg
stc
jmp short read_exit
read_disk endp
;-----------------------------------------------------------------------
; Find file - Searches the root directory for a filename.
; Entry: SI - Ptr to file name to find
; Exit: CF - Clear if found.
; DI - If CF clear, ptr to entry containing file name.
;-----------------------------------------------------------------------
find_file proc near
mov cx,root_size ;Get number of entries
mov di,ROOT_DIR
findfile_1:
push cx
push si
push di
mov cx,11 ;Compare names in entry
repe cmpsb
pop di
pop si
pop cx
je findfile_2
add di,32 ;Point to next entry
loop findfile_1
stc
ret
findfile_2:
clc
ret
find_file endp
;-----------------------------------------------------------------------
; Print Line
; Entry: SI - Ptr to string to print.
;-----------------------------------------------------------------------
print_line proc near
lodsb
or al,al
je findfile_2
mov ah,0eh
mov bx,7
int 10h
jmp short print_line
print_line endp
;-----------------------------------------------------------------------
; CLUSTER2SECTOR - Convert cluster number into sector number.
; Entry: AX - Cluster to read
; Exit: AX - Sector number
; CX - Cluster size
;-----------------------------------------------------------------------
cluster2sector proc near
dec ax ;Compensate for 1st to FAT
dec ax ; entries not being used.
xor cx,cx ;Compute the starting sector
mov cl,sec_per_cluster
mul cx ;CX, number of sectors to read
add ax,data_startl
adc dx,data_starth
ret
cluster2sector endp
;-----------------------------------------------------------------------
; LOAD FIRST - Reads the first cluster of a file.
; Entry: BX - Destination buffer
; DI - Ptr to directory entry
;-----------------------------------------------------------------------
load_first proc near
mov ax,[di+1ah] ;Get starting cluster
mov di,ax ;Save starting cluster
call cluster2sector ;Read 1st cluster.
call read_disk
ret
load_first endp
;-----------------------------------------------------------------------
; Load and Boot
; Entry: SI - Ptr to file name to load and boot
; Exit: This routine will not return if boot file found.
; CF - Set if boot file not found.
; SI - Offset of error message.
;-----------------------------------------------------------------------
load_and_boot proc near
assume cs:code,ds:code
call find_file ;Find filename in dir list
jnc lab_1
lab_error:
mov di,offset bootfile ;Copy name of boot file
mov cx,11 ; not found.
rep movsb
xor ax,ax ;Terminate string
stosb
mov si,offset mbootlost_msg
ret
lab_1:
mov bx,300h ;Offset to load extended boot
call load_first ;Read first cluster of file
jc lab_error
pop ax ;Remove local return address
mov dl,boot_disk
mov si,partition_ptrl
xor ax,ax ;Set up expected segment config
push ax
mov ah,7ch
push ax
retf
load_and_boot endp
;-----------------------------------------------------------------------
; Data used by the Boot record.
;-----------------------------------------------------------------------
mboot_name db "MBOOT SYS"
lastboot_name db "LASTBOOTBIN"
bootfail_msg db "Boot Failure",13,10,0
readerr_msg db "Disk Error",0
mbootlost_msg db "Can",27h,"t find file "
bootfile = $
org 2FEh
dw 0aa55h ;Boot record flag
;============================================================================
;============================================================================
; This part of Multiboot is loaded by the boot record.
;============================================================================
;============================================================================
boot_extend_start = $
jmp boot_extend
org 303h
boot_ptr_array = $
boot_data_ptr dw offset boot_data1 - offset boot_extend_start
boot_data_size dw offset boot_data1_end - offset boot_data1
boot_sess_ptr dw offset boot_array - offset boot_extend_start
boot_sess_size dw offset boot_array_end - offset boot_array
boot_ostab_ptr dw offset opsys_table - offset boot_extend_start
boot_ostab_size dw offset opsys_table_end - offset opsys_table
boot_version dw 05h
boot_data1 = $
last_choice dw 1 ;Boot session currently active
last_opsys db 1 ;Last operating system booted.
last_DOS db 1 ;Last DOS version booted
boot_default db 0 ;Default boot session
boot_timeout dw 0 ;Time until default
opsys_clusters dw 0 ;Size of original op sys files
time_stamp dd 0 ;Time stamp to verify disk.
boot_data1_end = $
fat_seg_low dw FAT_SEGMENT1
fat_seg_high dw FAT_SEGMENT2
fat_mask dw 0
fat_size dw 0
load_error db "Boot extend load error",13,10,0
;-------------------------------------------------------------------------
; GET FATTYPE - Determines if the FAT is 12 bit or 16 bit.
; Entry: BP - Pointer to boot data structure.
; Exit: fat_mask initialized
;-------------------------------------------------------------------------
get_fattype proc near
mov si,0fff8h ;Assume 16 bit FAT
xor dx,dx
mov ax,total_sec
or ax,ax ;If total sectors = 0, huge
jne get_fattype_1 ; partition.
mov ax,word ptr total_sec_long
mov dx,word ptr total_sec_long[2]
get_fattype_1:
xor cx,cx ;If more than 4087 clusters,
mov cl,sec_per_cluster ; assume 16 bit FAT.
div cx
cmp ax,4087
ja get_fattype_2
mov si,0ff8h ;Set 12 bit FAT mask
get_fattype_2:
mov fat_mask,si ;Save FAT mask
mov fat_size,ax
ret
get_fattype endp
;-------------------------------------------------------------------------
; GET FAT ENTRY - Finds a FAT entry from index
; Entry: BP - Pointer to boot data structure.
; DI - Entry into FAT table
; Exit: DI - Next entry
; CF - Clear if last entry
;-------------------------------------------------------------------------
get_fat_entry proc near
push bx
push ds
push es
mov dx,fat_mask ;Get FAT mask
mov es,fat_seg_high ;Load DS and ES with segments
mov ds,fat_seg_low ; containing the FAT table.
mov bx,di ;Copy index number
add bx,di
mov ax,ds:[bx] ;Assume low segment of 16 bit
jnc get_fat_entry_1 ; FAT.
mov ax,es:[bx] ;CF set, high segment
get_fat_entry_1:
or dx,dx ;Test for 12 or 16 bit FAT
js get_fat_entry_3
mov bx,di
shr di,1 ;12 bit FAT
mov ax,ds:[bx+di]
jnc get_fat_entry_2
mov cl,4 ;If odd index, shift
shr ax,cl
get_fat_entry_2:
and ah,0fh ;Clear top nibble
get_fat_entry_3:
mov di,ax ;Copy entry data
cmp ax,dx ;See if last entry
pop es
pop ds
pop bx
ret
get_fat_entry endp
;-------------------------------------------------------------------------
; LOAD FILE1 - Loads a file by reading the FAT table (Skips first cluster)
; Entry: BP - Pointer to boot data structure.
; ES:BX - Destination buffer
; DI - Entry into FAT table
; Exit: CF - Set if error
;-------------------------------------------------------------------------
load_file1 proc near
load_file_1:
call get_fat_entry
jnc load_file_exit
push bx
call cluster2sector ;Read next cluster
call read_disk
pop bx
jc load_file_exit1
add bx,bytes_per_clust ;Update read destination
jmp short load_file_1
load_file_exit:
clc
load_file_exit1:
ret
load_file1 endp
debug_msg5 db ".",0
;====================================================================
; BOOT EXTEND
; Entry: DL - Boot Disk
; SI - Pointer to booted partition table entry
; DI - Starting cluster for this file
;====================================================================
boot_extend proc near
mov ax,790h ;Reload CS and DS.
mov ds,ax
mov es,ax
push ax
mov ax,offset extend_load_0
push ax
retf
;
; Since MBOOT.SYS may be larger than one cluster, the FAT table must be read
; and interpeted. This next section of code must reside in the first
; 512 bytes of MBOOT.SYS.
;
extend_load_0:
mov hi_fat_size,0
mov ax,sec_per_fat ;Compute size of FAT
mov cx,ax
mul bytes_per_sec
or dx,dx ;See if larger than 64K
je extend_load_1 ;Compute the max number of
mov dx,1 ; sectors in 64K.
xor ax,ax
div bytes_per_sec
mov cx,ax ;Copy sectors to read
extend_load_1:
mov low_fat_size,cx
mov ax,FAT_SEGMENT1
mov es,ax
xor bx,bx
mov ax,fat_sectorl ;Get starting sector of FAT
mov dx,fat_sectorh
push cx
call read_disk ;Read FAT
pop cx
jc extend_read_error
mov ax,cx ;If FAT larger than 64K
sub cx,sec_per_fat ; read remainder into second
jbe extend_load_2 ; segment.
mov hi_fat_size,cx
mov bx,FAT_SEGMENT2
mov es,bx
xor bx,bx
mov dx,bx
add ax,fat_sectorl ;Get ptr to remainder of FAT
adc dx,fat_sectorh
call read_disk ;Read FAT
jc extend_read_error
extend_load_2:
push cs ;Restore ES
pop es
call get_fattype ;See if 12 or 16 bit fat
xor ax,ax
mov al,sec_per_cluster
mul bytes_per_sec
mov bytes_per_clust,ax ;Save bytes per cluster
mov bx,ax ;BX = dest for file data. Add
add bx,300h ; size of boot rec + 100h
call load_file1 ;Read remainder of MBOOT.SYS
jnc extend_load_3
extend_read_error:
mov si,offset load_error ;Indicate load error
jmp boot_error
;
; MBOOT.SYS fully loaded. Get on with displaying the menu.
;
extend_load_3:
mov screen_rows,25 ;Configure screen
mov normal_attr,COLOR_NORM
mov highlight_attr,COLOR_HIGH
xor ax,ax
int 11h ;Get screen type
mov bx,0003h ;Set video mode 3
test ax,10h ;See if color or BW
jz boot_extend_00
mov bx,0007h ;Set video mode 7
mov normal_attr,BW_NORM
mov highlight_attr,BW_HIGH
boot_extend_00:
mov ax,bx ;Set video mode.
call vidint
call write_box ;Write copyright box
boot_extend_01:
xor ax,ax
mov al,boot_default ;Copy defaults
push bp
mov bp,offset boot_menu
mov [bp+MENU_SELECTED],al
cmp al,0 ;If no default, no timeout
je extend_load_02
mov ax,boot_timeout
extend_load_02:
mov [bp+MENU_TIMEOUT],ax
call menu
pop bp
cmp bl,0 ;If no choice, ask again.
je boot_extend_01
call scroll_half ;Clear screen
cmp bx,last_choice ;See if the choice is the same
jne boot_extend_11 ; as last time.
jmp boot_extend_boot ;Yes, boot with old files.
boot_extend_11:
push bx
call get_entry ;Get ptr to new entry
mov di,bx
pop bx
xchg last_choice,bx ;Save new choice, get last
mov old_choice,bx ;Save in case of write error
call get_entry ;Compute offset of old entry
mov al,[di+OSTYPE_OFFSET] ;If the operating system is
cmp al,last_opsys ; different from the last
je boot_extend_2 ; one, read the os files.
mov bl,al ;See if OS/2 or DOS op sys.
call get_os_entry
cmp word ptr [di+OPSYS_TYPE],100h ;If OS/2 skip file
jae boot_extend_22 ; copying.
cmp al,last_DOS ;If last DOS version same,
je boot_extend_22 ; skip file copy.
push ax ;Tell user we are changing
push bx ; the DOS files.
mov si,offset change_os_msg
call write_linenorm
pop bx
pop ax
mov last_DOS,al
call load_os_files ;Read the DOS system files
mov si,offset read_os_error
jc boot_extend_write_error1
call write_os_files ;Write DOS sys files to disk
jc boot_extend_write_error1
push ax
xor ax,ax
mov cx,ax
mov cl,number_of_fats
boot_extend_21:
call write_fat_table ;Write updated FAT to disk
inc ax
loop boot_extend_21
pop ax
boot_extend_22:
push ax
mov bl,last_opsys ;Rename the boot record file
call make_os_names ; to the name in the os table
mov di,si
mov si,offset lastboot_name
call rename_file
pop bx ;Get back the new op sys type
mov last_opsys,bl
call make_os_names ;Rename the new boot file to
call rename_file ; LASTBOOT.SYS
mov bx,old_choice ;Get prev session
call get_entry ;Compute offset of old entry
boot_extend_2:
lea di,[bx+AUTO_OFFSET] ;Rename the current AUTOEXEC
mov si,offset autoexec_name ; file to its old name
call rename_file
lea di,[bx+CONFIG_OFFSET] ;Rename the current CONFIG.SYS
mov si,offset config_name ; file to its old name.
call rename_file
mov bx,last_choice ;Rename saved files to
call get_entry ; CONFIG.SYS and AUTOEXEC.BAT
lea si,[bx+AUTO_OFFSET] ;Start with AUTOEXEC.BAT
mov di,offset autoexec_name
call rename_file
lea si,[bx+CONFIG_OFFSET] ;Now rename CONFIG.SYS
mov di,offset config_name
call rename_file
boot_extend_3:
mov ax,root_sectorl ;Write the Root directory back
mov dx,root_sectorh ; to the disk.
mov bx,ROOT_DIR
mov cx,root_bytes ;Get size of root directory
call write_disk
jnc boot_extend_4 ;If write error, Boot last
boot_extend_write_error:
mov si,offset boot_extend_err ; boot record.
boot_extend_write_error1:
call write_linenorm
mov bx,old_choice
jmp short boot_extend_boot
boot_extend_4:
mov si,offset mboot_name ;Find MBOOT again in dir list
call find_file
jc boot_extend_write_error
mov ax,[di+1ah] ;Get starting cluster
mov bx,300h
call cluster2sector ;Update the MBOOT boot table
call write_disk
jc boot_extend_write_error
mov bx,last_choice
boot_extend_boot:
call get_entry ;Print message to identify
push bx ; the session booting
mov si,bx
mov di,offset boot_sess_msg1
mov cx,NAME_LENGTH+1
rep movsb
mov si,offset boot_sess_msg
call write_linenorm
pop bx
mov bl,[bx+OSTYPE_OFFSET] ;Print message to identify
call get_os_entry ; operating system booting.
mov si,offset boot_os_msg1
xchg si,di
mov cx,9
rep movsb
mov si,offset boot_os_msg
call write_linenorm
mov dx,0d00h ;Row 13, Column 0
call set_cursor
mov si,offset lastboot_name ;Boot operating system.
call load_and_boot
jmp boot_halt ;If this returns, halt
boot_extend endp
;--------------------------------------------------------------------
; MENU querys the user menu selection.
; Entry: BP - Pointer to menu structure.
; Exit: BX - Menu item selected.
;--------------------------------------------------------------------
menu proc near
mov last_timeout,0
mov dx,[bp+MENU_TIMEOUT] ;Point to timeout line
mov timeout_value,dx ;Copy timeout value
or dx,dx ;If 0, no timeout
je menu_wrtprompt
mov si,offset timeout_str ;Ptr to timeout string
call write_linenorm
xor ax,ax ;Read system timer
int 1ah
add dx,timeout_value ;Set timeout value
mov timeout_value,dx
menu_wrtprompt:
mov dx,[bp+MENU_PROMPT] ;Write menu prompt
mov si,offset prompt_text
call write_line_at
key_loop:
call write_menu ;Write menu choices
key_loop_1:
mov ax,timeout_value
cmp ax,0 ;If timout not disabled, print
jne key_1 ; time remaining.
cmp ax,last_timeout
je key_2
mov last_timeout,ax
mov si,offset timetext1
call write_linenorm
jmp short key_2
key_1:
xor ax,ax ;Read system timer
int 1ah
mov ax,timeout_value
sub ax,dx ;Subtract current time
ja key_11 ;If no time, exit with
jmp key_quit ; carry.
key_11:
mov cx,18
xor dx,dx
div cx
inc ax
cmp ax,last_timeout
je key_2
mov last_timeout,ax
mov dx,173ch ;Write time remaining
call hex2asc
mov dx,1a00h ;Hide cursor
call set_cursor
key_2:
cmp no_DOS_flag,0
je key_3
int 28h ;Call DOS idle
key_3:
call get_key ;Get key from keyboard
jz key_loop_1 ;No key available, loop
cmp al,0dh ;If CR, exit.
je key_exit
cmp al,27 ;If ESC, quit.
je key_quit
cmp al,3 ;If Ctl-C, quit.
je key_quit
cmp al,31h ;If valid number jump
jb key_down_0 ; directly to selection.
cmp al,39h
ja key_down_0
sub al,30h
call check_valid ;See if selection valid
jc key_loop_1 ;No, get another key
jmp short key_loop_2
key_down_0:
cmp al,9 ;Tab
je key_down_1
cmp ah,4dh ;Right
je key_down_1
cmp ah,50h ;Down
jne key_up_1
key_down_1:
mov al,[bp+MENU_SELECTED]
key_down_2:
inc al
cmp al,[bp]
jbe key_down_3
mov al,1
key_down_3:
call check_valid ;See if selection valid
jc key_down_2
jmp short key_loop_2
key_up_1:
cmp ax,0f00h ;Back Tab
je key_up_2
cmp ah,4bh ;Left
je key_up_2
cmp ah,48h ;Up
je key_up_2
jmp key_loop_1
key_up_2:
mov al,[bp+MENU_SELECTED]
key_up_3:
sub al,1
ja key_loop_2
mov al,[bp]
key_loop_2:
call check_valid ;See if selection valid
jc key_up_3
mov [bp+MENU_SELECTED],al
mov timeout_value,0 ;Disable timeout
jmp key_loop
key_exit:
clc
key_exit1:
mov bh,0
mov bl,[bp+MENU_SELECTED] ;Get menu item selected
ret
key_quit:
stc
jmp short key_exit1
menu endp
;--------------------------------------------------------------------
; GET KEY gets a key from the keyboard.
; Exit: AX - key returned
; ZF - Set if no key
;--------------------------------------------------------------------
get_key proc near
mov ah,1
int 16h ;Check for key
jz get_key_1
mov ah,0
int 16h ;Get key
or ax,ax
get_key_1:
ret
get_key endp
;--------------------------------------------------------------------
; FETCH KEY waits for and gets a key from the keyboard
; Exit: AX - key returned
;--------------------------------------------------------------------
fetch_key proc near
int 28h ;Call DOS idle
call get_key ;Read a key from the keyboard
jz fetch_key
ret
fetch_key endp
;--------------------------------------------------------------------
; CHECK VALID determines if a menu selection is valid.
; Entry: BP - Pointer to menu structure.
; AL - Menu selection
; Exit: CF - Clear if valid selection
;--------------------------------------------------------------------
check_valid proc near
push ax
push di
dec al
cmp al,[bp] ;See if beyond choices
ja check_valid_bad
xor ah,ah ;Convert selection into
shl ax,1 ; index into menu structure
shl ax,1
lea di,[bp+MENU_FIRSTITEM] ;Get ptr to 1st item
add di,ax
mov si,[di+2] ;Get location of string
or al,[si] ;If 1st byte > 80h, disabled
js check_valid_bad ; item.
clc
check_valid_exit:
pop di
pop ax
ret
check_valid_bad:
stc
jmp short check_valid_exit
check_valid endp
;--------------------------------------------------------------------
; WRITE MENU displays the choices on the screen.
; Entry: BP - Pointer to menu structure.
;--------------------------------------------------------------------
write_menu proc near
xor cx,cx
mov cl,[bp] ;Get number of choices
xor bx,bx
lea di,[bp+MENU_FIRSTITEM] ;Get ptr to 1st item
write_menu_1:
inc bh ;Inc menu item counter
mov si,[di+2] ;Get location of string
cmp byte ptr [si],80h ;If 1st byte > 80h, disabled
jae write_menu_3 ; item, don't print.
mov dx,[di] ;Get location of item
mov al,bh ;Print menu item number
call printnum
add dl,4
mov si,[di+2] ;Get location of string
cmp bh,[bp+MENU_SELECTED] ;If selected, use highlight
jne write_menu_2 ; attribute.
call write_line_hi
jmp short write_menu_3
write_menu_2:
call write_line_at
write_menu_3:
add di,4 ;Point to next item
loop write_menu_1
mov dx,[bp+MENU_PROMPT]
add dl,8
call set_cursor ;Set cursor pos
mov al,[bp+MENU_SELECTED] ;Get current selection
or al,al
je write_menu_exit
add al,30h
mov ah,0ah ;BIOS Write Char
mov cx,1 ;1 character
xor bx,bx
call vidint
write_menu_exit:
ret
write_menu endp
;--------------------------------------------------------------------
; GETENTRY - Computes the offset of a boot array entry given the
; entry number
; Entry: BL - Entry number
; Exit: BX - Offset of that entry
;--------------------------------------------------------------------
get_entry proc near
mov ax,offset boot_array
get_entry1:
push ax ;Save start of table
dec bx
mov al,NEXT_ENTRY ;Multiply the size of
mul bl ; each entry by the
pop bx ; number then add the
add bx,ax ; starting offset.
ret
get_entry endp
;--------------------------------------------------------------------
; GET OS ENTRY - Computes offset of entry in the op sys table.
; Entry: BL - Operating system number. 1 - 4
; Exit: DI - Pointer to entry in op sys table.
;--------------------------------------------------------------------
get_os_entry proc near
push ax
push bx
xor bh,bh
dec bl
mov al,NEXT_OSENTRY
mul bl
add ax,offset opsys_table
mov di,ax
pop bx
pop ax
ret
get_os_entry endp
;--------------------------------------------------------------------
; LOAD_FILE - Computes offset of entry in the op sys table.
; Entry: ES:BX - Destination buffer
; DI - Ptr to directory table entry
; BP - Boot data ptr
;--------------------------------------------------------------------
load_file proc near
push bx
call load_first
pop bx
add bx,bytes_per_clust
call load_file1
ret
load_file endp
;--------------------------------------------------------------------
; LOAD_OS_FILES - Reads the operating system files into memory.
; Entry: AL - Operating system number
; BP - Boot data ptr
;--------------------------------------------------------------------
load_os_files proc near
push ax
push bx
mov bl,al
call make_os_names ;Make op sys names
add si,11 ;Point to IO.SYS name
call find_file ;Find the filename
jc load_os_files_exit
mov cx,[di+1ch] ;Read file size
mov new_io_size,cx
push di
add si,11 ;Point to MSDOS.SYS
call find_file ;Find the filename
mov si,di
pop di
jc load_os_files_exit
mov cx,[si+1ch] ;Read file size
mov new_dos_size,cx
mov ax,DATA_SEG1
mov es,ax
xor bx,bx
push si
call load_file ;Read IO.SYS
pop di
jc load_os_files_exit
mov ax,DATA_SEG2
mov es,ax
xor bx,bx
call load_file ;Read MSDOS.SYS
load_os_files_exit:
push cs ;Restore ES
pop es
pop bx
pop ax
ret
load_os_files endp
;--------------------------------------------------------------------
; WRITE_OS_FILES - Writes the operating system files onto the disk.
; Entry: BP - Boot data ptr
; AL - Operating system number
;--------------------------------------------------------------------
write_os_files proc near
push ax
push bx
mov bx,ax ;Copy os number
call get_os_entry
mov cx,[di+OPSYS_TYPE] ;Get os config
cmp cx,50h
je write_os_files_0
mov ax,1 ;At least 1 cluster needed
cmp cx,40h ; for DOS 4 type os
jae write_os_files_02
mov ax,new_io_size ;Get clusters needed for
xor dx,dx ; files.
div bytes_per_clust
inc ax
push ax ;Save clusters for IO.SYS
xor ax,ax
cmp cx,30h ;If DOS 3 type os, only IO.SYS
jae write_os_files_01 ; size needs to be checked
mov ax,new_dos_size
xor dx,dx
div bytes_per_clust
inc ax
write_os_files_01:
pop dx ;Get IO.SYS clusters needed
add ax,dx
write_os_files_02:
push ax ;Save clusters needed
push bx
call check_fat ;See if enough room for opsys
pop bx ; files.
pop dx
cmp dx,cx
mov si,offset no_room_error
ja write_os_files_err1
write_os_files_0:
mov cx,new_io_size ;Get size of new IO.SYS
add di,9 ;Point to IO.SYS name
mov si,di ;Copy entry in op sys table
mov di,ROOT_DIR ;Get ptr to root dir
push cx
push di
call clear_file ;Remove IO.SYS from FAT
add di,20h ;Point to next file
call clear_file ;Remove MSDOS.SYS from FAT
call clean_fat ;Remove any bad cluster flags
mov ax,DATA_SEG1 ;Get seg of IO.SYS data
mov es,ax
mov dx,1 ;Look for 1st free cluster.
call find_free_clust
mov dx,di
pop di
pop cx
call store_os_file ;Write IO.SYS to disk
jc write_os_files_exit
add di,20h ;Point to next dir entry
add si,11 ;Point to MSDOS.SYS name
mov cx,new_dos_size ;Get size of new MSDOS.SYS
mov ax,DATA_SEG2 ;Get seg of MSDOS.SYS data
mov es,ax
call store_os_file ;Write MSDOS.SYS to disk
jc write_os_files_exit
mov bx,opsys_clusters ;Get number of sys sectors
inc bx
mov di,dx
mov ax,0fff7h ;Bad sector flag
cmp bx,di
jb write_os_files_2
write_os_files_1:
call write_fat_entry ;Fill in empty sectors with
inc di ; bad sector flags.
cmp bx,di
jae write_os_files_1
write_os_files_2:
clc
write_os_files_exit:
push cs ;Restore ES
pop es
pop bx
pop ax
ret
write_os_files_err:
mov si,offset write_os_error
write_os_files_err1:
stc
jmp short write_os_files_exit
write_os_files endp
;-----------------------------------------------------------------------
; STORE OS FILE - Writes an operating system file to the disk
; Entry: DX - Starting Cluster of file
; CX - Size of file
; SI - New file name
; DI - Ptr to directory entry
; ES - Segment of file data
; Exit: DX - Next free cluster
; CF - Set if error
;-----------------------------------------------------------------------
store_os_file proc near
push di
push si
push es
push ds
pop es
push di ;First, copy new name to
push cx ; dir entry.
mov cx,11
rep movsb
pop cx
pop di
pop es
mov [di+1Ah],dx ;Save new starting cluster
mov [di+1Ch],cx ;Save size in dir entry
xor bx,bx ;Start at beginning of buffer
store_os_file_1:
mov ax,dx ;Copy cluster to write
push bx
push cx
push dx
call cluster2sector ;Convert to sector number
call write_disk ;Write cluster to disk
pop dx
pop cx
pop bx
add bx,bytes_per_clust ;Update read dest
sub cx,bytes_per_clust ;Sub bytes written from size
ja store_os_file_11
mov di,dx ;Get new cluster
mov ax,-1 ;Write -1 to FAT entry to
call write_fat_entry ; indicate end of file.
call find_free_clust ;Get next free cluster
mov dx,di ;Copy ptr to free cluster
store_os_file_exit:
pop si
pop di
ret
store_os_file_11:
call find_free_clust ;Get next free cluster
jc store_os_file_exit
mov ax,di ;Copy new FAT entry
xchg di,dx ;Xchg old, new FAT entries
call write_fat_entry ;Write new cluster to old FAT
jmp short store_os_file_1 ; entry. Loop back for more.
store_os_file endp
;-----------------------------------------------------------------------
; FIND FREE CLUST - Finds the next free cluster in the FAT
; Entry: DX - Current cluster
; Exit: DI - Next free cluster
; CF - Set if no free clusters
;-----------------------------------------------------------------------
find_free_clust proc near
push dx
find_free_clust_1:
inc dx ;First, check to see if at
cmp fat_size,dx ; end of FAT.
jb find_free_clust_exit
mov di,dx ;Scan through FAT to find next
push dx ; entry with 0, indicating
call get_fat_entry ; free cluster.
pop dx
or di,di ;See if cluster = 0 -> free
jne find_free_clust_1 ;No, keep looking
mov di,dx ;Copy free cluster
clc
find_free_clust_exit:
pop dx
ret
find_free_clust endp
;-----------------------------------------------------------------------
; CHECK FAT - Counts the number of consecutive clusters at the start of
; the disk.
; Exit: CX - Count of available clusters.
;-----------------------------------------------------------------------
check_fat proc near
push di
mov di,ROOT_DIR
mov bx,[di+1Ah] ;Get starting cluster. If not
call get_fat_chain ; consecutive clusters, skip
jc check_fat_1 ; msdos.sys check.
inc bx
mov si,bx ;Save ending cluster
add di,20h ;Point to MSDOS.SYS entry
mov bx,[di+1Ah] ;Get starting cluster
cmp si,bx
jne check_fat_6
call get_fat_chain
add cx,si ;Sum consec clusters.
check_fat_1:
inc bx
mov ax,fat_mask ;Convert FAT mask into bad
mov al,0f7h ; sector detector
check_fat_2:
mov di,bx ;Copy ptr to last FAT entry
push cx
push ax ;Count the number of bad
call get_fat_entry ; sectors at the end of
pop ax ; the system files.
pop cx
or di,di ;See if sector free.
je check_fat_3
cmp di,ax ;See if sector marked bad
jne check_fat_4
check_fat_3:
inc bx ;Inc FAT pointer
inc cx ;Inc Count
jmp short check_fat_2
check_fat_4:
clc
check_fat_5:
pop di
ret
check_fat_6:
stc
jmp short check_fat_1
check_fat endp
;-----------------------------------------------------------------------
; CLEAN FAT - Removes bad cluster markers used to reserve clusters.
;-----------------------------------------------------------------------
clean_fat proc near
mov di,2 ;Start at cluster 2
mov bx,fat_mask
and bl,0f7h ;Create Bad entry mask
or bl,0f7h
clean_fat_1:
push di
call get_fat_entry ;See if entry marked bad
cmp di,bx
pop di
jne clean_fat_2 ;No, skip write.
xor ax,ax
call write_fat_entry ;Clear entry
clean_fat_2:
inc di ;Point to next entry
mov ax,opsys_clusters
add ax,2
cmp di,ax
jbe clean_fat_1
ret
clean_fat endp
;-----------------------------------------------------------------------
; GET FAT CHAIN - Follows a FAT chain for a file.
; Entry: BX - Ptr to start of chain
; Exit: CX - Count of consecutive clusters
; BX - Last entry in FAT table.
; CF - Set if file not in consecutive clusters
;-----------------------------------------------------------------------
get_fat_chain proc near
push di
xor cx,cx
mov di,bx
get_fat_chain_1:
inc cx
mov bx,di ;Copy FAT entry ptr
push cx
call get_fat_entry
pop cx
mov ax,bx
jnc get_fat_chain_2 ;CF = 0, last entry
sub bx,di ;See if consecutive
cmp bx,-1
je get_fat_chain_1
stc
get_fat_chain_2:
mov bx,ax ;Get back last FAT entry
pop di
ret
get_fat_chain endp
;-------------------------------------------------------------------------
; CLEAR FILE - Removes the FAT table entries for a file.
; Entry: BP - Pointer to boot data structure.
; DI - Pointer to directory entry
;-------------------------------------------------------------------------
clear_file proc near
push di
push si
mov bx,[di+1Ah] ;Get starting cluster
clear_file_1:
mov di,bx ;Save FAT pointer
call get_fat_entry
pushf ;Save end of file flag
xchg di,bx
xor ax,ax
call write_fat_entry ;Zero entry to free cluster
popf
jc clear_file_1
pop si
pop di
ret
clear_file endp
;-------------------------------------------------------------------------
; WRITE FAT ENTRY - Writes FAT table entry
; Entry: BP - Pointer to boot data structure.
; DI - Pointer to fat table entry
; AX - Data to write to FAT table
;-------------------------------------------------------------------------
write_fat_entry proc near
push ax
push bx
push dx
push di
push ds
push es
mov ds,fat_seg_low ;Load DS and ES with segments
mov es,fat_seg_high ; containing the FAT table.
mov dx,cs:fat_mask ;Mask data to FAT size.
or dl,-1
and ax,dx
xor dx,dx
or dx,cs:fat_mask ;Mask unwanted bits
jns write_fat_4 ;If 0fffh, 12 bit FAT
mov bx,di ;16 bit FAT
add di,bx ;Ptr = Index * 2
jnc write_fat_2 ;CF = 1, Upper segment
write_fat_1:
mov es:[di],ax ;Write data
jmp short write_fat_3
write_fat_11:
or ax,bx
write_fat_2:
mov ds:[di],ax ;Write data
write_fat_3:
pop es
pop ds
pop di
pop dx
pop bx
pop ax
ret
write_fat_4:
mov bx,di
shr di,1 ;12 bit FAT
pushf
add di,bx
mov bx,ds:[di] ;Get data
popf
jc write_fat_5 ;Jump if odd
and bx,0f000h ;Remove old data
jmp short write_fat_11
write_fat_5:
and bx,000fh ;Remove old data
push cx
mov cl,4
shl ax,cl
pop cx
jmp short write_fat_11
write_fat_entry endp
;-----------------------------------------------------------------------
; WRITE FAT TABLE - Writes data in memory FAT to disk FAT.
; Entry: AX - FAT number to write
;-----------------------------------------------------------------------
write_fat_table proc near
push ax
push cx
push es
mov cx,sec_per_fat ;Compute starting sector
mul cx ; of this FAT
add ax,fat_sectorl
adc dx,fat_sectorh
push ax
push dx
mov bx,FAT_SEGMENT1
mov es,bx
xor bx,bx
mov cx,low_fat_size
call write_disk ;Write FAT
pop dx
pop ax
jc write_fat_table_exit
xor cx,cx
or cx,hi_fat_size
je write_fat_table_exit
add ax,cx
adc dx,0
mov bx,FAT_SEGMENT2
mov es,bx
xor bx,bx
call write_disk
write_fat_table_exit:
pop es
pop cx
pop ax
ret
write_fat_table endp
;-----------------------------------------------------------------------
; RENAME FILE
; Entry: SI - Ptr to file name to find
; DI - Ptr to new file name.
;-----------------------------------------------------------------------
rename_file proc near
push di
push si
cmp byte ptr [di],0 ;See if filename exists
je rename_1
push di ;Save ptr to new file name
call find_file
pop si
jc rename_1
mov cx,11 ;Copy name to entry.
rep movsb
clc
rename_1:
pop di
pop si
ret
rename_file endp
;-----------------------------------------------------------------------
; MAKE OS NAMES
; Entry: BL - Operating System number
; Exit: SI - Ptr array of 8.3 op sys names
;-----------------------------------------------------------------------
make_os_names proc near
push bx
mov si,offset os_names_table
add bl,"0"
mov [si+7],bl
mov [si+18],bl
mov [si+29],bl
pop bx
ret
make_os_names endp
;--------------------------------------------------------------------
; WRITE VERT
;--------------------------------------------------------------------
write_vert proc near
lodsw ;Get location
mov dx,ax
write_vert1:
mov di,dx ;Save cursor pos
call set_cursor
lodsb
or al,al
je write_vert2
mov ah,0ah ;BIOS Write Char
mov cx,1 ;1 character
call vidint
mov dx,di ;Get cursor pos
inc dh
call set_cursor
jmp short write_vert1
write_vert2:
ret
write_vert endp
;--------------------------------------------------------------------
; WRITE LINENORM
;Entry: SI - Offset of ASCIIZ string with leading word detailing
; row and column to start string.
;--------------------------------------------------------------------
write_linenorm proc near
push dx
lodsw ;Get location
mov dx,ax
call write_line_at
pop dx
ret
write_linenorm endp
;--------------------------------------------------------------------
; WRITE LINE AT/HI
;Entry: DX - Row/Column to start string
; SI - Offset of ASCIIZ string
;--------------------------------------------------------------------
write_line_hi proc near
mov bl,highlight_attr ;Write with highlight attribute
jmp short write_line_at1
write_line_hi endp
write_line_at proc near
mov bl,normal_attr
write_line_at1:
call set_cursor
call write_line
ret
write_line_at endp
;--------------------------------------------------------------------
; WRITE LINE
;Entry: BL - Attribute for line
; SI - Offset of ASCIIZ string
;--------------------------------------------------------------------
write_line proc near
push bx
push cx
push dx
push di
xor bh,bh ;Set video page
mov di,dx ;Save cursor pos
write_line_1:
lodsb
or al,al
je write_line_2
mov ah,09h ;BIOS Write Char/Attr
mov cx,1 ;1 character
call vidint
inc di
mov dx,di ;Get cursor pos
call set_cursor
jmp short write_line_1
write_line_2:
pop di
pop dx
pop cx
pop bx
ret
write_line endp
;--------------------------------------------------------------------
;WRITE BORDER
;--------------------------------------------------------------------
write_border proc near
call set_cursor
mov ax,0acdh ;Write border
mov cx,59
call vidint
ret
write_border endp
;--------------------------------------------------------------------
; WRITE BOX writes copyright box to the screen.
;--------------------------------------------------------------------
write_box proc near
call scroll_scr
xor bx,bx
mov bl,normal_attr
mov dx,010bh
call write_border
mov dx,050bh
call write_border
mov si,offset box1
call write_vert
mov si,offset box2
call write_vert
mov si,offset boxtext1 ;Point to 1st line
mov cx,3
title1: mov bl,normal_attr ;Set attribute
call write_linenorm
loop title1
ret
write_box endp
;-----------------------------------------------------------------------------
; VIDINT - Calls the BIOS int 10h. Saves BP to correct bug in old PC BIOS.
;-----------------------------------------------------------------------------
vidint proc near
push bp
int 10h
pop bp
ret
vidint endp
;-----------------------------------------------------------------------------
; SCROLL SCR Clears the screen.
;-----------------------------------------------------------------------------
scroll_scr proc near
xor cx,cx
mov dh,screen_rows
mov dl,50h
call scroll_block
ret
scroll_scr endp
;-----------------------------------------------------------------------------
; SCROLL HALF Clears the screen below the copyright box.
;-----------------------------------------------------------------------------
scroll_half proc near
mov cx,0700h ;Row 7 Col 0
mov dx,1950h
call scroll_block
ret
scroll_half endp
;-----------------------------------------------------------------------------
; SCROLL BLOCK Clears a part of the screen.
; Entry: CX - Upper left corner
; DX - Lower right corner
;-----------------------------------------------------------------------------
scroll_block proc near
push bx
xor bx,bx
mov bh,normal_attr
mov ax,0600h ;Scroll up
call vidint
pop bx
ret
scroll_block endp
;-----------------------------------------------------------------------------
; SCROLL BLOCK Clears a part of the screen.
; Entry: DX - Cursor Location
;-----------------------------------------------------------------------------
set_cursor proc near
push ax
push bx
mov ah,02h ;Set cursor
xor bx,bx
call vidint
pop bx
pop ax
ret
set_cursor endp
;-----------------------------------------------------------------------------
; PRINTNUM - Prints a single digit number to the screen.
; Entry: AL - binary number
; DX - Cursor location
;-----------------------------------------------------------------------------
printnum proc near
add al,30h
mov si,offset number_buff
mov [si],al
call write_line_at ;Write number
ret
printnum endp
;-----------------------------------------------------------------------------
; HEX2ASC converts a binary number to ASCII and prints it to the screen.
; Entry: AX - binary number
;-----------------------------------------------------------------------------
hex2asc proc near
call set_cursor
xor cx,cx
mov cl,1 ;If number = 0, print 1
or ax,ax ; zero.
jne hex_0
mov al,"0"
jmp short hex_1
hex_0:
mov cl,3 ;Allow max of three digits
hex_loop1:
xor dx,dx ;Clear high word
mov bx,10 ;Load number base
div bx ;Divide by base (10)
add dl,30h ;Convert to ascii
push dx ;Save digit on stack
loop hex_loop1
mov cx,3 ;Allow max of three digits
mov bl,"0" ;Set leading zero indicator
hex_loop2:
pop ax ;Get digit off stack
or bl,al ;Don't print leading zeros.
cmp bl,"0" ;The first non zero will
jne hex_1 ; change bl to non-zero.
mov al,20h
hex_1:
push bx
mov ah,0eh ;Write TTY
mov bl,12h
call vidint
pop bx
loop hex_loop2
hex_exit:
ret
hex2asc endp
;-----------------------------------------------------------------------------
; Extended boot data.
;-----------------------------------------------------------------------------
boot_data_start = $
boot_array = $
name1 db "DOS Session ",0
auto1 db "AUTOEXECMB1"
config1 db "CONFIG MB1"
ostype1 db 1 ;Index into op sys table
name2 db NAME_LENGTH dup (80h),0
db "AUTOEXECMB2"
db "CONFIG MB2"
db 0
name3 db NAME_LENGTH dup (80h),0
db "AUTOEXECMB3"
db "CONFIG MB3"
db 0
name4 db NAME_LENGTH dup (80h),0
db "AUTOEXECMB4"
db "CONFIG MB4"
db 0
boot_array_end = $
opsys_table = $
os_name1 db 8 dup (80h),0 ;Name of operating system
os_ioname db "IO SYS" ;IO.SYS file name
os_comname db "MSDOS SYS" ;MSDOS.SYS file name
os_boottype dw 0
os_name2 db 8 dup (80h),0
db "OS2LDR "
db "OS2KRNL "
dw 0
os_name3 db 8 dup (80h),0
db "BIOS SYS"
db "DOS SYS"
dw 0
os_name4 db 8 dup (80h),0
db "BIOS SYS"
db "DOS SYS"
dw 0
opsys_table_end = $
boot_data_end = $
normal_attr db COLOR_NORM
highlight_attr db COLOR_HIGH
screen_rows db 0
last_timeout dw 0
timeout_value dw 0
no_DOS_flag db 1 ;0 = No DOS resident.
number_buff db 0,".",0
read_os_error db 2,7,"Error Reading new DOS files",0
write_os_error db 2,7,"Error Writing new DOS files",0
no_room_error db 2,7,"Not enough room for new DOS files",0
boot_extend_err db 2,7,"Write error, Last choice booted.",0
change_os_msg db 2,7,"Changing DOS System files",0
boot_os_msg db 2,11,"Operating System: "
boot_os_msg1 db NAME_LENGTH+1 dup (0)
boot_sess_msg db 2,9,"Booting Session: "
boot_sess_msg1 db 9 dup (0)
timeout_str db 41,23,"Time until default:",0
timetext1 db 61,23,"Indefinite",0
prompt_text db "Choice [ ]",0
autoexec_name db "AUTOEXECBAT" ;Filenames to rename.
config_name db "CONFIG SYS"
ibmbio_name db "IBMBIO COM" ;IBM DOS system file names
ibmcom_name db "IBMDOS COM"
iosys_name db "IO SYS" ;MS DOS system file names
msdos_name db "MSDOS SYS"
os_names_table db "MBOOTOSaBOT" ;This array is used to hold
db "MBOOTOSaSYS" ; the generated names of the
db "MBOOTOSaCOM" ; DOS system files.
;
; Boot Menu structure
;
boot_menu = $
menu_struc db 4 ;Number of choices
selected db 0 ;Selected Item
prompt_loc db 30,20 ;Location of "Choices" prompt
timeout dw 0 ;Timeout value
db 40,23 ;Col, Row of Timeout string
firstitem db 24,9 ;Column, Row of menu item
dw offset name1 ;Offset of menu text
db 24,11
dw offset name2
db 24,13
dw offset name3
db 24,15
dw offset name4
boxtext1 db 27,02,"PC Magazine",39,"s MultiBoot 1.0",0
boxtext2 db 26,03,"(c) 1991 Ziff Communications",0
boxtext3 db 32,04,"Douglas Boling",0
box1 db 10,01,201,186,186,186,200,0 ;"╔","║","║","║","╚"
box2 db 69,01,187,186,186,186,188,0 ;"╗","║","║","║","╝"
;============================================================================
;============================================================================
; Start of installation code and data.
;============================================================================
;============================================================================
even
install_start = $
inst_text1 db "Session Title AUTOEXEC File "
db "CONFIG File System",0
main_menu db 8,0 ;Number of choices, Selected
db 30,22 ;Location of "Choices" prompt
dw 0 ;Timeout value
db 0,0 ;Col, Row of Timeout string
db 13,17 ;Column, Row of menu item
dw offset add_entry ;Offset of menu text
db 13,18
dw offset delete_entry
db 13,19
dw offset set_default
db 13,20
dw offset add_osentry
db 40,17
dw offset install
db 40,18
dw offset remove
db 40,19
dw offset exit_prog
db 40,20
dw offset quit_prog
confirm_msg db 20,16,"Do you wish to discard changes?",0
yes_text db "Yes",0
no_text db "No",0
yesno_menu db 2,1 ;Number of choices, Selected
db 25,22 ;Location of "Choices" prompt
dw 0 ;Timeout value
db 0,0 ;Col, Row of Timeout string
db 25,18 ;Column, Row of menu item
dw offset yes_text ;Offset of menu text
db 25,20
dw offset no_text
add_entry db "Add Session",0
delete_entry db "Delete Session",0
set_default db "Set Defaults",0
add_osentry db "Load Operating System",0
install db "Install MultiBoot",0
remove db "Remove MultiBoot",0
exit_prog db "Update and Exit MultiBoot",0
quit_prog db "Quit MultiBoot",0
return_text db "Update and Return",0
quit_text db "Return Without Changing",0
unused_text db "< Unused >",0
unused_text_end = $
os2knl_name db "OS2KRNL "
os2ldr_name db "OS2LDR "
os2boot_aname db "C:\OS2\SYSTEM\BOOT.OS2",0
default_str db "Def.",0
command_table dw offset main_menu ;Offset of menu for this table
dw offset main_add ;Command jump table
dw offset main_delete
dw offset main_defaults
dw offset main_osadd
dw offset main_install
dw offset main_remove
dw offset exit
dw offset quit
dos_version dw 0
installed_flag db 0 ;Set if MultiBoot installed
changed_flag db 0
local_changed db 0
huge_flag db 0 ;Set if target disk > 32M
targ_sec_per_cluster dw 0
session_count db 0 ;Number of used sessions
opsys_count db 0 ;Number of operating systems
iosys_size dw 0 ;Size of IO.SYS read
doscom_size dw 0 ;Size of MSDOS.SYS read
opsys_ostype dw 0 ;DOS File config
databuff_ptr dd 0 ;Pointer to data buffer
databuff1_ptr dd 0 ;Pointer to second data buffer
crit_vec dd 0 ;Saved critical error vector
ctlc_vec dd 0 ;Saved control C vector
ctlc_stack dw 0
ctlc_return dw 0
drive_letter db "A" ;Target drive
installed_data = $
db 3 dup (0) ;Bytes for jump instruction
inst_data_ptr dw 0 ;Offset of last boot data
inst_data_size dw 0 ;Size of last boot data
inst_sess_ptr dw 0 ;Offset of boot session table
inst_sess_size dw 0 ;Size of boot session table
inst_boot_ptr dw 0 ;Offset of boot os table
inst_boot_size dw 0 ;Size of boot os table
inst_version dw 0 ;Version of installed code
installed_data_end = $
key_buffer db 64 dup (0)
temp_buff db 64 dup (0)
filename_buff db 20 dup (0)
temp dw 0 ;Temp storage buffer
errmsg0 db "Requires at least DOS 2.x$"
errmsg1 db "This program cannot be run under OS/2$"
errmsg2 db "Not enough memory for MultiBoot$"
errmsg3 db "Too many open files$"
errmsg4 db "Access to files denied$"
errmsg5 db "Drive Letter not specified on command line$"
errmsg6 db "Drive Letter invalid$"
errmsg7 db "MultiBoot file MBOOT.SYS not found$"
errmsg8 db "Not a bootable disk or unknown operating system$"
errmsg9 db "MultiBoot must be run in 80 column mode$"
errmsg10 db "Installed data is incompatible with this version$"
crmsg db 13,10,"$"
error_msg_loc dw 180ah ;Column, Row of error msgs
errmsg20 db "Install error",0
errmsg21 db "MultiBoot Already Installed",0
errmsg22 db "Remove error",0
errmsg23 db "MultiBoot Not Installed",0
;-----------------------------------------------------------------------------
; Prevent Abort,Retry,Ignore error msg with this dummy crit. error routine
;-----------------------------------------------------------------------------
crit_error proc far
mov al,0 ;Ignore critical error.
iret
crit_error endp
;-----------------------------------------------------------------------------
; Installation code.
;-----------------------------------------------------------------------------
main proc near
assume ds:code
cld ;Set string operations up
mov ah,30h ;Get DOS version, run only
int 21h ; if 2.0 or greater.
xchg al,ah ;Swap major, minor numbers
mov dx,offset errmsg0 ;Bad DOS version
cmp ah,2
jb jmp1_error_exit
mov dx,offset errmsg1 ;Program cannot be run in the
cmp ah,10 ; DOS box under OS/2.
jae jmp1_error_exit
mov dos_version,ax ;Save version number
mov sp,offset end_of_code + 512 ;Move stack
mov ah,4ah ;Reduce memory alloc
mov bx,offset end_of_code + 527
mov cl,4
shr bx,cl
int 21h
int 12h ;Get size of machine RAM
cmp ax,384 ;Must be at least 384K to
mov dx,offset errmsg2 ; use extended boot code.
jb jmp1_error_exit
mov ah,48h ;Allocate memory block for
mov bx,1000h ; data buffer.
int 21h
mov dx,offset errmsg2 ;Not enough memory msg
jc jmp1_error_exit
mov word ptr databuff_ptr[2],ax ;Save segment.
mov ah,48h ;Allocate memory block for
mov bx,1000h ; second data buffer.
int 21h
mov dx,offset errmsg2 ;Not enough memory msg
jc jmp1_error_exit
mov word ptr databuff1_ptr[2],ax ;Save segment.
call set_ctlc_vec ;Setup Control-C routine
mov si,81h ;Point to command line tail
xor cx,cx
or cl,[si-1] ;Get cmd tail length
jne main_2
main_1:
mov dx,offset errmsg5 ;Drive letter not specified.
jmp1_error_exit:
jmp error_exit
main_2:
lodsb
cmp al,13 ;See if end of line
je main_1 ;If so, error.
cmp al," "
ja main_3
loop main_2
jmp short main_1
main_3:
cmp byte ptr [si],":" ;Make sure drive letter
jne main_1 ; terminated by colon.
and al,0dfh ;Convert drive letter to
cmp al,"A" ; upper case.
jb main_1
cmp al,"Z"
ja main_1
mov drive_letter,al ;Save drive letter
call set_crit_vec ;Set crit vec to int routine
call huge_disk_check ;See if target disk > 32 Meg
call reset_crit_vec
mov dx,offset errmsg6
jc jmp1_error_exit
je main_not_huge
inc huge_flag ;If so, set flag
main_not_huge:
mov targ_sec_per_cluster,di
call check_os ;See what system on target
cmp al,-1 ; disk.
mov dx,offset errmsg6 ;See if error reading disk.
je jmp1_error_exit
push ax
xor al,al ;Copy BIOS parameter block
call copy_bpb ; to boot rec data area.
pop ax
cmp al,3 ;See if MultiBoot installed
je main_installed
mov dx,offset errmsg8 ;If OS unknown or unbootable,
cmp al,2 ; error.
jae jmp1_error_exit
call setup_multiboot ;Not installed, setup.
jmp short main_5
main_installed:
inc installed_flag ;Set installed flag
call get_inst_data ;Read data from MBOOT.SYS
jc jmp1_error_exit
main_5:
mov cx,4
mov si,offset opsys_table ;Count sessions and op systems
mov di,offset boot_array
add di,OSTYPE_OFFSET
main_count_loop:
cmp byte ptr [si],80h ;If lead byte 80h, entry
jae main_6 ; unused.
inc opsys_count ;Inc number of op systems
main_6:
cmp byte ptr [di],0 ;Op Sys = 0, no session.
je main_7
inc session_count
main_7:
add di,NEXT_ENTRY ;Point to next entries
add si,NEXT_OSENTRY
loop main_count_loop
push ds
mov ax,40h ;Get number of screen rows
mov ds,ax
mov dl,[84h]
pop ds
mov screen_rows,dl
mov ah,0fh ;Read video mode
call vidint
mov dx,offset errmsg9 ;Must be in 80 column mode
cmp ah,80
jb error_exit
cmp al,0fh ;Check for BW modes
je main_set_bw
cmp al,6
jb main_set_color
cmp al,7
ja main_set_color
main_set_bw:
mov normal_attr,BW_NORM ;Use Black/White attributes
mov highlight_attr,BW_HIGH
main_set_color:
call write_box ;Write copyright box
main_loop:
mov di,offset name1 ;Display current sessions
call disp_settings
mov local_changed,0
mov si,offset command_table ;Display menu and jump to
mov al,1 ; proper routine. Default
call jump_menu ; to Add Session.
pushf
cmp al,-1 ;See if exit
je main_exit
add changed_flag,al ;Set flag if mboot modified.
call scroll_half
popf
jnc main_loop ;If carry, print message
call write_error ;Print error message
jmp short main_loop
error_exit:
mov ah,9 ;Print error message
int 21h
mov dx,offset crmsg
mov ah,9 ;Insert carrage return
int 21h
mov al,1
jmp short main_exit1
main_exit:
popf ;Remove flags from stack
mov dx,0700h ;Set cursor to Row 7 Column 0.
call set_cursor
xor ax,ax ;Clear return code
main_exit1:
push ax
mov ax,word ptr databuff_ptr[2] ;Get segment.
or ax,ax
je main_exit2
mov es,ax
mov ah,49h ;Free data buffer
int 21h
main_exit2:
mov ax,word ptr databuff1_ptr[2] ;Get segment.
or ax,ax
je main_exit3
mov es,ax
mov ah,49h ;Free data buffer
int 21h
main_exit3:
pop ax
mov ah,4ch
int 21h
main endp
;--------------------------------------------------------------------
; SETUP MULTIBOOT - Configures Multiboot if not installed.
; Entry: AX - Operating system on target disk
; BX - DOS version
; CX - Consecutive clusters used by DOS files
;--------------------------------------------------------------------
setup_multiboot proc near
push ax ;Save operating system type
push bx ; and size.
mov opsys_clusters,cx
mov ah,2ch ;Get system time for time
int 21h ; stamp ID
mov word ptr time_stamp,cx
mov word ptr time_stamp[2],dx
pop cx ;Get os config
pop ax ;Get os type
mov bl,1 ;The current os becomes the
call copy_os_name ; default.
mov si,offset boot_extend_start ;Copy installed data ptrs
mov di,offset installed_data
mov cx,offset installed_data_end - offset installed_data
rep movsb
cmp ah,1 ;See if OS/2 installed
jne setup_multiboot_1
mov dx,offset os2boot_aname ;Yes, look for BOOT.OS2
mov cl,drive_letter
mov byte ptr os2boot_aname,cl
push es
les si,databuff_ptr ;Read OS/2 boot record file.
call read_file
pop es
jc setup_multiboot_1
mov bl,2
mov cx,100h ;OS type = OS/2
call copy_os_name ;Copy OEM name.
setup_multiboot_1:
mov bl,1 ;Verify default session
call get_entry ; filenames are not used.
mov cx,8
setup_multiboot_2:
lea si,[bx+AUTO_OFFSET] ;Search for the filenames used
call find_first ; in the default session. If
jnc setup_multiboot_3 ; used, rename by changing
lea si,[bx+CONFIG_OFFSET] ; the extension.
call find_first
jc setup_exit
setup_multiboot_3:
inc byte ptr [bx+AUTO_OFFSET+10]
inc byte ptr [bx+CONFIG_OFFSET+10]
loop setup_multiboot_2 ;If all filenames used
mov byte ptr [bx+OSTYPE_OFFSET],0 ; delete default.
setup_exit:
ret
setup_multiboot endp
;--------------------------------------------------------------------
; GET INST DATA - Reads the configutation data from MBOOT.SYS
; Exit: CF - Set if error
; DX - Offset of error message.
;--------------------------------------------------------------------
get_inst_data proc near
mov si,offset mboot_name ;Open the MBOOT.SYS file to
call make_filename ; read the boot information.
xor cx,cx
call set_attributes ;Clear the file attributes.
mov ax,3d02h
int 21h
jc get_inst_file_error
mov bx,ax ;Copy file handle
mov ah,3fh ;Read ptr to boot table
mov dx,offset installed_data
mov cx,offset installed_data_end - offset installed_data
int 21h
jc get_inst_file_error
mov dx,offset errmsg10 ;See if installed data
cmp inst_version,20h ; compatible
jae get_inst_data_error
mov ax,4200h ;Move file ptr
mov dx,inst_data_ptr
xor cx,cx
int 21h
jc get_inst_file_error
mov ah,3fh ;Read default session data
mov dx,offset boot_data1
mov cx,inst_data_size
int 21h
jnc get_inst_data_1
get_inst_file_error:
mov dx,offset errmsg7 ;Boot file error.
cmp ax,2 ;See if file not found
je get_inst_data_error ;Yes, error
mov dx,offset errmsg3 ;See if too many files opened
cmp ax,4
je get_inst_data_error
mov dx,offset errmsg4 ;Assume access denied
get_inst_data_error:
stc
jmp short get_inst_data_exit
get_inst_data_1:
mov ax,4200h ;Move file ptr to session table
mov dx,inst_sess_ptr
xor cx,cx
int 21h
jc get_inst_file_error
mov ah,3fh ;Read boot session data
mov dx,offset boot_array
mov cx,inst_sess_size
int 21h
jc get_inst_file_error
mov ax,4200h ;Move file ptr to session table
mov dx,inst_boot_ptr
xor cx,cx
int 21h
jc get_inst_file_error
mov ah,3fh ;Read boot session data
mov dx,offset opsys_table
mov cx,inst_boot_size
int 21h
jc get_inst_file_error
mov ah,3eh ;Close file
int 21h
mov si,offset mboot_name ;Set MBOOT.SYS file attributes
call make_filename ; to hidden, system, and
mov cx,SYSFILE_ATTR ; read only.
call set_attributes
jc get_inst_file_error
get_inst_data_exit:
ret
get_inst_data endp
;--------------------------------------------------------------------
; MAIN ADD - Displays the Add Session submenu.
;--------------------------------------------------------------------
local_add1 db NEXT_ENTRY dup (0) ;Local copy of boot table
local_add2 db NEXT_ENTRY dup (0)
local_add3 db NEXT_ENTRY dup (0)
local_add4 db NEXT_ENTRY dup (0)
local_add_end = $
local_add_count db 0
local_selection dw 0 ;Current selected session
local_add_menu = $
db 4 ;Number of choices
add_select db 0 ;Selected Item
db 30,20 ;Location of "Choices" prompt
dw 0 ;Timeout value
db 0, 0 ;Col, Row of Timeout string
db 24,9 ;Column, Row of menu item
dw offset local_add1 ;Offset of menu text
db 24,11
dw offset local_add2
db 24,13
dw offset local_add3
db 24,15
dw offset local_add4
add_str2 db 20,7
add_select_str1 db "Current Sessions",0
add_add_text db "Add Session",0
add_rename_text db "Rename Session",0
add_str4 db 05,14,"Enter the title of the session:",0
add_str7 db 15,16,"Is this correct?",0
add_str_msg1 db 10,22,"Press Ctrl-Break to return to Add Menu",0
add_str_err1 db "No Sessions Added",0
add_str_err2 db "No free sessions, delete a session first",0
add_table dw offset add_menu
dw offset add_add_sess
dw offset add_rename
dw offset add_exit
dw offset add_quit
add_menu db 4,0 ;Number of choices, Selected
db 30,22 ;Location of "Choices" prompt
dw 0 ;Timeout value
db 0,0 ;Col, Row of Timeout string
db 25,17 ;Column, Row of menu item
dw offset add_add_text ;Offset of menu text
db 25,18
dw offset add_rename_text
db 25,19
dw offset return_text
db 25,20
dw offset quit_text
main_add proc near
assume cs:code,ds:code
mov di,offset local_add1 ;Copy boot array
mov si,offset boot_array
mov cx,4 ;4 Entries.
main_add_0:
push cx ;Copy the contents of the
mov cx,NEXT_ENTRY ; marked unused, replace
mov bx,di
rep movsb
cmp byte ptr [bx+OSTYPE_OFFSET],0 ;See if session unused.
jne main_add_02
mov byte ptr [bx+AUTO_OFFSET],0 ;If unused, clear
mov byte ptr [bx+CONFIG_OFFSET],0 ; filename entries
mov byte ptr [bx],80h
main_add_02:
pop cx
loop main_add_0
mov al,session_count ;Copy session count
mov local_add_count,al
main_add_1:
mov di,offset local_add1 ;Display current sessions.
call disp_settings
mov si,offset add_table ;Display the add menu
mov al,1
call jump_menu ;Call submenu routines
pushf ;Save carry flag
pop bx
cmp al,-1
jne main_add_1
mov al,local_changed ;Indicate if changes made.
push bx ;Restore carry flag if needed
popf
ret
;--------------------------------------------------------------------
; ADD ADD SESSION - adds an entry to the boot table.
;--------------------------------------------------------------------
add_add_sess proc near
call scroll_half
xor bx,bx
mov bl,local_add_count ;Get number of sessions.
cmp bl,4 ;See if too many
jb add_add_sess_1
mov si,offset add_str_err2
call write_error ;Print error message
jmp add_add_sess_exit
add_add_sess_1:
mov cx,4
xor bx,bx ;Find first free boot table
mov si,offset local_add1 ; entry.
add_add_sess_11:
inc bx
cmp byte ptr [si+OSTYPE_OFFSET],0
je add_add_sess_12
add si,NEXT_ENTRY
loop add_add_sess_11
add_add_sess_12:
call get_sess_name ;Get session name
jnc add_add_sess_13
jmp_add_add_sess_5:
jmp add_add_sess_5
add_add_sess_13:
mov local_selection,bp
mov si,offset autoexec_name ;Point to AUTOEXEC.BAT name
call add_file
jc jmp_add_add_sess_5
mov di,local_selection ;Copy AUTOEXEC filename to
add di,AUTO_OFFSET ; local array.
mov cx,12
rep movsb
mov si,offset config_name ;Point to CONFIG.SYS name
call add_file
jc add_add_sess_5
mov di,local_selection ;Copy CONFIG filename to
add di,CONFIG_OFFSET ; local array.
mov cx,12
rep movsb
mov dh,10
call clear_line
mov di,local_selection ;Write session data to screen
call disp_session
mov dh,14
call clear_line
add_add_sess_2:
mov bl,1 ;Assume only one OS.
cmp opsys_count,1
je add_add_sess_3 ;If only one OS, don't display
call get_ostype ; OS menu.
or bl,bl
je add_add_sess_2 ;Must select an os.
add_add_sess_3:
mov di,local_selection ;Set OS type
add di,OSTYPE_OFFSET
mov byte ptr [di],bl
mov dh,10
call clear_line
mov di,local_selection ;Write session data to screen
call disp_session
mov al,1
mov si,offset add_str7 ;Ask user to verify changes.
call msg_box
cmp bl,1 ;See if Yes.
je add_add_sess_4
mov di,local_selection ;If no, clear entries
mov byte ptr [di],80h ; and return to
mov byte ptr [di+AUTO_OFFSET],0 ; add menu.
mov byte ptr [di+CONFIG_OFFSET],0
mov byte ptr [di+OSTYPE_OFFSET],0
jmp short add_add_sess_exit
add_add_sess_4:
mov local_changed,1 ;Set changes flag
inc local_add_count ;Inc number of sessions
add_add_sess_5:
call scroll_half
add_add_sess_exit:
xor al,al
ret
add_add_sess endp
;--------------------------------------------------------------------
; ADD RENAME SESSION - Renames a session.
;--------------------------------------------------------------------
add_rename proc near
mov bp,offset local_add_menu
xor ax,ax
call get_session_2 ;Ask for a session
jc add_rename_session_exit
or bx,bx ;See if no choice
jz add_rename_session_exit
call get_sess_name ;Ask for a session name
jc add_rename_session_exit
mov local_changed,1
add_rename_session_exit:
call scroll_half
xor al,al ;Clear exit flag
ret
add_rename endp
;--------------------------------------------------------------------
; ADD EXIT - Copies the local data to the main boot table then sets
; the exit flag
;--------------------------------------------------------------------
add_exit proc near
mov bx,offset local_add1
mov dx,offset boot_array
mov cx,4 ;4 Entries.
main_add_5:
push cx ;Copy only entrys used.
mov si,bx
mov di,dx
cmp byte ptr [bx+OSTYPE_OFFSET],0 ;See of entry used.
je main_add_6
mov cx,NEXT_ENTRY
rep movsb
main_add_6:
add dx,NEXT_ENTRY
add bx,NEXT_ENTRY
pop cx
loop main_add_5
mov al,local_add_count ;Copy new number of sessions
mov session_count,al
mov al,-1 ;Set exit flag
ret
add_exit endp
;--------------------------------------------------------------------
; ADD QUIT - Querys user for verification then returns exit flag
;--------------------------------------------------------------------
add_quit proc near
xor al,al
cmp local_changed,0 ;See if any changes made
je add_quit_1
call confirm_quit
jne add_quit_exit
mov si,offset add_str_err1 ;No changes message.
mov local_changed,0 ;Clear changes flag
add_quit_1:
mov al,-1 ;Set exit flag
add_quit_exit:
ret
add_quit endp
main_add endp
;--------------------------------------------------------------------
; MAIN DELETE - Deletes an entry to the boot table.
;--------------------------------------------------------------------
local_delete dw 4 dup (0) ;Delete flag for each session
delete_str2 db 20,07
del_select db "Select Session to Delete",0
delete_str3 db 15,11,"Do you want to delete the CONFIG.SYS"
db " and AUTOEXEC.BAT",0
delete_str4 db 15,12,"files for this Session?",0
delete_err1 db "Can",39,"t delete active session.",0
tbdel_text db "To Be Deleted ->",0
delete_table dw offset delete_menu
dw offset delete_delete_session
dw offset delete_exit
dw offset add_quit
delete_menu db 3,0 ;Number of choices, Selected
db 30,22 ;Location of "Choices" prompt
dw 0 ;Timeout value
db 0,0 ;Col, Row of Timeout string
db 25,18 ;Column, Row of menu item
dw offset del_select ;Offset of menu text
db 25,19
dw offset return_text
db 25,20
dw offset quit_text
main_delete proc near
assume cs:code,ds:code
xor ax,ax ;Clear local delete flags.
mov di,offset local_delete
stosw
stosw
stosw
stosw
xor bx,bx
main_delete_1:
push bx
popf
jnc main_delete_2
call write_error
main_delete_2:
mov bp,offset boot_menu ;Display sessions
call write_menu ; in menu form.
mov cx,4
mov dx,word ptr firstitem ;Starting cursor loc from
mov dl,5 ; boot menu structure.
mov si,offset local_delete
main_delete_3:
lodsw
or al,al ;See if session to be deleted
je main_delete_4 ;No, skip
push si
mov si,offset tbdel_text
call write_line_at
pop si
main_delete_4:
inc dh ;Move to next cursor location
inc dh
loop main_delete_3
;Display delete menu.
mov si,offset delete_table ;Display the delete menu
mov al,1
call jump_menu
pushf ;Save carry flag
pop bx
cmp al,-1 ;See if exit flag set
jne main_delete_1
mov al,local_changed ;Indicate if changes made.
push bx ;Restore carry flag if needed
popf
ret
;--------------------------------------------------------------------
; DELETE DELETE SESSION - Querys the user for the session to delete
;--------------------------------------------------------------------
delete_delete_session proc near
mov al,0 ;Get session to delete.
call get_session
jc delete_delete_exit
cmp bx,last_choice ;Make sure not deleting
jne delete_delete_0 ; current session.
mov si,offset delete_err1
xor al,al
stc
jmp short delete_delete_exit1
delete_delete_0:
push bx
call scroll_half ;See if we need to delete the
mov si,offset delete_str3 ; CONFIG.SYS and AUTOEXEC.BAT
call write_linenorm ; files.
mov si,offset delete_str4
mov al,2
call msg_box
mov ah,bl ;Copy yes no answer
pop bx ;Restore selection to delete
jnc delete_delete_1
mov ah,2 ;If <esc> force No reply.
delete_delete_1:
dec ah
dec bx
shl bx,1
mov al,1
mov [bx+local_delete],ax ;Save delete flags for this
call scroll_half ; selection.
delete_delete_exit:
xor al,al ;Clear exit flag
delete_delete_exit1:
ret
delete_delete_session endp
;--------------------------------------------------------------------
; DELETE EXIT - Performs the delete of sessions requested then sets
; the error flag.
;--------------------------------------------------------------------
delete_exit proc near
mov cx,4
mov si,offset local_delete ;Set ptr to delete selections
mov di,offset name1 ;Point to 1st session title
delete_exit_1:
lodsw ;Get flag for selection
or al,al ;Delete entry?
je delete_exit_3
mov byte ptr [di+OSTYPE_OFFSET],0 ;Delete entry in list
or byte ptr [di],80h
dec session_count
mov local_changed,1 ;Set changed flag
mov dl,5
sub dl,cl
cmp dl,boot_default ;If entry just deleted was
jne delete_exit_2 ; the default, remove default.
mov boot_default,0
delete_exit_2:
or ah,ah ;Should the AUTOEXEC and
jne delete_exit_3 ; CONFIG files be deleted?
push si
lea si,[di+AUTO_OFFSET] ;Yes, delete files
call delete_file
lea si,[di+CONFIG_OFFSET]
call delete_file
pop si
delete_exit_3:
add di,NEXT_ENTRY ;Point to next session title
loop delete_exit_1
mov al,-1 ;Set exit flag
ret
delete_exit endp
main_delete endp
;--------------------------------------------------------------------
; INST OSADD - Adds an operating system to the disk.
;--------------------------------------------------------------------
osadd_str0 db 25,07,"Current Operating Systems",0
osadd_str1 db 10,08,"Insert Diskette with new DOS system"
db " into Drive A:",0
osadd_str2 db 10,10,"Press any key when Diskette inserted.",0
osadd_str3 db 10,08,"Insert Target diskette into Drive A:",0
osadd_str4 db 10,08,"Current Operating System name: "
osadd_namestr db 9 dup (0)
osadd_str5 db 10,10,"New Operating System name:",0
osadd_str6 db 10,10,"Reading DOS System files",0
osadd_str7 db 10,10,"Writing DOS System files",0
osadd_dos5 db 15,16,"Are you installing DOS 5.0 or greater?",0
osadd_dos4 db 15,16,"Are you installing DOS 4.0 or greater?",0
osadd_dos3 db 15,16,"Are you installing DOS 3.0 or greater?",0
osadd_err1 db "Only four operating systems can be added",0
osadd_err2 db "Can",39,"t delete last operating system",0
osadd_err3 db "Diskette is not a bootable DOS diskette",0
osadd_err4 db "MultiBoot installed on diskette",0
osadd_err5 db "OS/2 cannot be installed from diskette",0
osadd_err6 db "Error writing DOS System files to the disk",0
osadd_err7 db "Operating system used by a session. Delete session "
db "first",0
osadd_err8 db "New DOS system files larger than original DOS system"
db " files",0
osadd_err9 db "Target disk not original MultiBoot disk."
db " DOS system not loaded",0
osadd_err10 db "MultiBoot must be installed before adding"
db " an Operating System",0
osadd_err11 db "Error updating MBOOT.SYS file",0
osa_addos_text db "Add an operating system",0
osa_delos_text db "Delete an operating system",0
osa_renos_text db "Rename an operating system",0
osadd_table dw offset osadd_menu
dw offset osadd_add_opsys
dw offset osadd_del_opsys
dw offset osadd_ren_opsys
dw offset osadd_exit
osadd_menu db 4,0 ;Number of choices, Selected
db 30,22 ;Location of "Choices" prompt
dw 0 ;Timeout value
db 0,0 ;Col, Row of Timeout string
db 25,17 ;Column, Row of menu item
dw offset osa_addos_text ;Offset of menu text
db 25,18
dw offset osa_delos_text
db 25,19
dw offset osa_renos_text
db 25,20
dw offset return_text
main_osadd proc near
assume cs:code,ds:code
xor bx,bx ;First time, no error.
main_osadd_1:
push bx ;Check for carry indicating
popf ; an error message display
jc main_osadd_2
call scroll_half ;Clear screen
main_osadd_2:
mov si,offset osadd_str0 ;Display current op systems
call write_linenorm
xor cx,cx
mov cl,opsys_count ;Four operating systems
mov dx,0920h
mov si,offset opsys_table ;Point to the opsys table
main_osadd_3:
push si
call write_line_at
pop si
add si,NEXT_OSENTRY
add dh,2
loop main_osadd_3
;Display os add menu.
mov si,offset osadd_table ;Display the op sys add menu
mov al,1
call jump_menu
pushf ;Save carry flag
pop bx
cmp al,-1 ;See if exit flag set
jne main_osadd_1
xor ax,ax ;Indicate if changes made.
push bx ;Restore carry flag if needed
popf
ret
;--------------------------------------------------------------------
; OSADD ADD OPSYS - Adds an operating system to the disk.
;--------------------------------------------------------------------
osadd_add_opsys proc near
mov si,offset osadd_err1 ;Only room for four operating
cmp opsys_count,4 ; systems.
jae jmp_osadd_error
mov si,offset osadd_err10 ;Must be installed message
cmp installed_flag,0
je jmp_osadd_error
mov si,offset osadd_str1 ;Prompt user for opsys
call write_linenorm ; diskette.
mov si,offset osadd_str2
call write_linenorm
call fetch_key ;Read a key from the keyboard
call clear_msg ;Clear message off screen
mov si,offset osadd_str6 ;Reading files message
call write_linenorm
mov al,"A" ;Set disk A
call get_opsys ;Read operating sys from disk
mov ah,0 ;Ignore OS/2 flag
push ax ;Save os type
push cx
push dx
pushf ;Save error flag
cmp drive_letter,"A"
jne osadd_add_3
mov si,offset osadd_str3 ;Prompt user for target
call write_linenorm ; diskette.
mov si,offset osadd_str2
call write_linenorm
call fetch_key ;Read a key from the keyboard
osadd_add_3:
call clear_msg ;Clear message off screen
popf ;Restore error flags
pop dx ;Restore IO.SYS size
pop cx ;Restore DOS system size
pop ax ;Restore os type
jnc osadd_add_11
mov si,offset osadd_err8
cmp al,7 ;See if Op sys too big
je jmp_osadd_error
mov si,offset osadd_err4
cmp al,3 ;See if Multiboot diskette
je jmp_osadd_error
mov si,offset osadd_err5
cmp al,2 ;See if OS/2 diskette
je jmp_osadd_error
mov si,offset osadd_err3
cmp al,1 ;See if diskette is bootable
jbe osadd_add_11
jmp_osadd_error:
jmp osadd_error
osadd_add_11:
call chk_mboot_disk ;See that proper disk is in
mov si,offset osadd_err9 ; drive.
jc jmp_osadd_error
cmp opsys_ostype,50h
je osadd_add_14
mov si,offset osadd_dos5 ;Ask user if installing DOS 5
mov di,50h
cmp opsys_clusters,0
je osadd_add_12
mov si,offset osadd_dos4 ;Ask user if installing DOS 4
mov di,40h
cmp huge_flag,0 ;If disk > 32 Meg, ask for
jne osadd_add_12 ; DOS 4
cmp dx,opsys_clusters
ja osadd_add_12
mov si,offset osadd_dos3 ;Ask user if installing DOS 3
mov di,30h
cmp cx,opsys_clusters
jb osadd_add_14
osadd_add_12:
push ax
push di
mov al,1 ;Set default to Yes
call msg_box
pop di
pop ax
cmp bl,1 ;See if answer Yes
mov si,offset osadd_err8
jne jmp_osadd_error
mov opsys_ostype,di ;Save new opsys type
osadd_add_14:
push ax ;Save os type
mov si,offset osadd_str7 ;Writing files message
call write_linenorm
inc opsys_count ;Inc count of operating systems
xor bx,bx
mov bl,opsys_count ;Get slot to place names
mov al,1 ;Copy BIOS param blk to
call copy_bpb ; new boot record.
pop ax ;Get opsys type
mov bp,ax
call put_opsys
mov si,offset osadd_err6 ;Error writing files
jc jmp_osadd_error
mov cx,4
mov si,offset opsys_table ;Find first empty entry in
xor bx,bx ; the op sys table.
osadd_add_32:
inc bl
cmp byte ptr [si],80h
jae osadd_add_33
add si,NEXT_OSENTRY
loop osadd_add_32
osadd_add_33:
mov cx,opsys_ostype ;Get DOS file config
mov ax,bp ;Copy the op sys name from
call copy_os_name ; the OEM name in the boot.
xor ax,ax
mov local_changed,1
ret
osadd_error:
call scroll_half ;Clear screen
call write_error ;Print error message
stc
ret
osadd_add_opsys endp
;--------------------------------------------------------------------
; OSADD DEL OPSYS - Deletes an operating system from the disk.
;--------------------------------------------------------------------
osadd_del_opsys proc near
mov si,offset osadd_err2 ;Delete. Don't delete active
cmp opsys_count,1 ; OS files.
jbe osadd_error
call get_ostype ;Query user for opsys
mov cx,4
mov si,offset osadd_err7 ;Check to see if os is in use
mov di,offset ostype1
osadd_del_opsys_1:
cmp [di],bl
je osadd_error
add di,NEXT_ENTRY
loop osadd_del_opsys_1
call delete_opsys ;Erase op sys files
osadd_del_opsys_exit:
dec opsys_count
xor ax,ax
mov local_changed,1
ret
osadd_del_opsys endp
;--------------------------------------------------------------------
; OSADD REN OPSYS - Renames an operating system on the disk.
;--------------------------------------------------------------------
osadd_ren_opsys proc near
call get_ostype ;Query user for OP SYS
or bl,bl
je jmp_osadd_1
push di ;Save ptr to op sys name
mov si,offset osadd_namestr
xchg di,si
mov cx,8 ;Only 8 characters in name
rep movsb
mov si,offset osadd_str4 ;Print old OS name
call write_linenorm
mov si,offset osadd_str5 ;Prompt user for new OS name
call write_linenorm
mov dx,0a29h
mov al,8 ;8 characters
call entry_box
pop di ;Get pointer to table entry
mov si,bx ;Copy ptr to new name
rep movsb ;Copy name
xor ax,ax
stosb ;Terminate name
mov local_changed,1
jmp_osadd_1:
xor ax,ax
ret
osadd_ren_opsys endp
;--------------------------------------------------------------------
; OSADD EXIT - Sets the exit flag to return from this submenu
;--------------------------------------------------------------------
osadd_exit proc near
cmp local_changed,0
clc
je osadd_exit_1
mov si,offset mboot_name ;Open the MBOOT.SYS file to
call make_filename ; write opsys information.
mov si,dx ;Copy ptr to ASCIIZ filename
xor cx,cx
call set_attributes ;Clear file attributes
mov ax,3d02h
int 21h
jc osadd_exit_error
mov bx,ax ;Copy file handle
mov ax,4200h ;Move file ptr to os table
mov dx,inst_boot_ptr
xor cx,cx
int 21h
mov ah,40h ;Write boot op sys data
mov dx,offset opsys_table
mov cx,inst_boot_size
int 21h
jc osadd_exit_error
mov ah,3eh ;Close file
int 21h
mov dx,si
mov cx,SYSFILE_ATTR
call set_attributes
jc osadd_exit_error
osadd_exit_1:
mov al,-1 ;Set exit flag
ret
osadd_exit_error:
mov si,offset osadd_err11
stc
jmp short osadd_exit_1
osadd_exit endp
main_osadd endp
;--------------------------------------------------------------------
; MAIN DEFAULTS - Sets boot default values
;--------------------------------------------------------------------
def_string1 db 20,08,"Current Defaults",0
def_string2 db 25,10,"Default Session:",0
def_string3 db 25,12,"Default Timeout:",0
def_string4 db 46,12,"Seconds",0
def_string6 db 15,14,"Enter Timeout Value in Seconds",0
default_msg1 db "Defaults Not Changed",0
default_msg2 db "No Default Session",0
default_msg3 db "Indefinite ",0
default_err1 db "Invalid number",0
local_timeout dw 0
local_default db 0
def_chdef db "Change Default Session",0
def_chtime db "Change Timeout",0
default_table dw offset default_menu
dw offset default_ch_def
dw offset default_ch_time
dw offset default_exit
dw offset add_quit
default_menu db 4,0 ;Number of choices, Selected
db 30,22 ;Location of "Choices" prompt
dw 0 ;Timeout value
db 0,0 ;Col, Row of Timeout string
db 25,17 ;Column, Row of menu item
dw offset def_chdef ;Offset of menu text
db 25,18
dw offset def_chtime
db 25,19
dw offset return_text
db 25,20
dw offset quit_text
main_defaults proc near
assume cs:code,ds:code
mov al,boot_default ;Copy system values to local
mov local_default,al ; variables.
mov ax,boot_timeout
mov local_timeout,ax
main_default_0:
mov si,offset def_string1
call write_linenorm
mov si,offset def_string2
call write_linenorm
mov si,offset def_string3
call write_linenorm
mov si,offset def_string4
call write_linenorm
main_default_1:
mov si,offset default_msg2 ;Point to no default msg
xor bx,bx
or bl,local_default ;Get pointer to default entry
je main_default_3
call get_entry
mov si,bx
main_default_3:
mov dx,0a2ah ;Row 10, Col 42
call write_line_at ;Write string
mov ax,local_timeout ;Get timeout value
or ax,ax
jne main_default_4
mov si,offset default_msg3 ;No timeout message
mov dx,0c2ah
call write_line_at
jmp short main_default_5
main_default_4:
xor dx,dx ;Convert to seconds
mov bx,18
div bx
mov dx,0c2ah ;Write default timeout
call hex2asc
main_default_5:
mov si,offset default_table
mov al,1
call jump_menu
cmp al,-1
jne main_default_0
mov al,local_changed
ret
;--------------------------------------------------------------------
; DEFAULT CH DEF - Changes the default session
;--------------------------------------------------------------------
default_ch_def proc near
mov al,local_default ;To select default session,
call get_session ; display menu of all
; sessions.
jc default_ch_def_1 ;If carry set or no selection
or bl,bl ; skip default set.
jc default_ch_def_1
mov local_default,bl ;Set new default
mov local_changed,1
default_ch_def_1:
xor al,al
ret
default_ch_def endp
;--------------------------------------------------------------------
; DEFAULT CH TIME - Changes the default timeout.
;--------------------------------------------------------------------
default_ch_time proc near
mov si,offset def_string6
call write_linenorm
mov dx,0e2fh ;Set cursor
mov al,3 ;Allow 3 characters
call get_number
jc default_ch_time_1 ;Carry set, error
mov dx,18 ;Convert seconds to ticks
mul dx
mov local_timeout,ax
mov local_changed,1
call scroll_half
ret
default_ch_time_1:
call scroll_half
mov si,offset default_err1 ;Illegal number
call write_error
ret
default_ch_time endp
;--------------------------------------------------------------------
; DEFAULT_EXIT - Copys the new default values to the boot table.
;--------------------------------------------------------------------
default_exit proc near
mov al,local_default ;Copy local value to system
mov boot_default,al ; values.
mov ax,local_timeout
mov boot_timeout,ax
mov al,-1
ret
default_exit endp
main_defaults endp
;--------------------------------------------------------------------
; INST INSTALL - Installs MultiBoot on a system.
;--------------------------------------------------------------------
install_msg1 db 15,9,"WARNING! You should back up your"
db " disk before",0
install_msg2 db 25,10,"installing MultiBoot.",0
install_msg db 15,16,"Do You wish to install MultiBoot?",0
install1_msg db 15,16,"Installing MultiBoot. Please wait.",0
install_nomsg db "MultiBoot not installed",0
main_install proc near
assume cs:code,ds:code
cmp installed_flag,0 ;See if already installed
je install_0
mov si,offset errmsg21
jmp install_error1
install_0:
mov si,offset install_msg1
call write_linenorm
mov si,offset install_msg2
call write_linenorm
mov si,offset install_msg
mov al,1 ;Set default to Yes
call msg_box
cmp bl,1 ;See if answer Yes
je install_01
mov si,offset install_nomsg ;Answer No, abort install.
jmp install_error1
install_01:
mov si,offset install1_msg
call write_linenorm
mov al,drive_letter
call get_opsys ;Get operating system
jc jmp_install_error
mov bx,101h ;Write operating system with
call put_opsys ; bootfile = LASTBOOT.BIN
jc jmp_install_error
mov si,offset mboot_name ;Write Boot extend file
call make_filename
mov si,offset boot_extend_start
mov cx,offset install_start - offset boot_extend_start
mov ax,SYSFILE_ATTR
mov no_DOS_flag,0
call write_file
mov no_DOS_flag,1
jc jmp_install_error
; Modify Multiboot boot record with data from original boot record.
push ds ;Compute the amount of
lds si,databuff_ptr ; boot data on old boot
mov di,100h ; record. If too much,
mov cx,ds:[si+1] ; don't install.
add cx,3
cmp byte ptr ds:[si],0e9h ;See if long jump
je install_2
cmp byte ptr ds:[si],0ebh ;See if short jmp
je install_1
pop ds
jmp_install_error:
jmp install_error ;If not a jump, error
install_1:
xor cx,cx
mov cl,ds:[si+1] ;Get size of data area
add cx,2 ;Add room for jmp
install_2:
cmp cx,offset bootcode - offset entry
ja install_error
rep movsb ;Copy boot data
pop ds
mov byte ptr cs:entry,0e9h ;Copy jump opcode
mov dx,offset bootcode - 103h ;Compute the jump value
mov word ptr cs:entry[1],dx
mov ax,dos_version
cmp ax,300h ;If DOS 2.x clear hidden sec
ja install_3 ; count.
mov bp,100h
mov word ptr num_hidden_sec,0
cmp ax,314h ;If DOS 3.0 - 3.2, clear high
ja install_3 ; word.
mov word ptr num_hidden_sec[2],0
install_3:
; Write Multiboot boot record to target drive.
mov al,drive_letter
mov bx,offset entry ;Get ptr to boot record
call put_bootrec
jc install_error
mov cx,4
mov si,offset opsys_table
add si,OPSYS_TYPE
mov bl,1
install_4:
cmp word ptr [si],100h ;See if OS/2 installed on
je install_5 ; disk.
inc bl
add si,NEXT_OSENTRY
loop install_4
jmp short install_6
install_5:
call make_os_names
call make_filename
mov di,si
mov dx,offset os2boot_aname
call copy_file
mov dx,di ;Hide boot file.
mov cx,SYSFILE_ATTR
call set_attributes
install_6:
mov changed_flag,0
mov installed_flag,1 ;Set install flag
xor al,al ;Clear error flag
install_exit1:
ret
install_error:
mov si,offset errmsg20
install_error1:
stc
jmp short install_exit1
main_install endp
;--------------------------------------------------------------------
; INST REMOVE - Removes Multiboot from a system.
;--------------------------------------------------------------------
remove_msg db 15,16,"Do you wish to remove MultiBoot?",0
remove1_msg db 15,16,"Removing MultiBoot. Please wait.",0
remove_nomsg db "MultiBoot not removed",0
main_remove proc near
assume cs:code,ds:code
; Check to see if already installed
cmp installed_flag,0 ;If not installed, don't
jne remove_1 ; remove.
mov si,offset errmsg23
jmp remove_error1
remove_1:
mov si,offset remove_msg ;Verify remove request.
mov al,1 ;Set default to Yes
call msg_box
cmp bl,1 ;See if answer Yes
mov si,offset remove_nomsg
jne remove_error1
mov si,offset remove1_msg ;Indicate removing.
call write_linenorm
mov si,offset lastboot_name ;Read current op sys boot
call make_filename ; record from the file.
push es
les si,databuff_ptr
call read_file ;Read LASTBOOT.BIN
pop es
jc remove_error
;Write old boot record to boot sector
mov al,drive_letter
push ds
lds bx,databuff_ptr ;Get ptr to data buffer
call put_bootrec ;Write the boot record
pop ds
jc remove_error
call fixup_fat ;Remove bad sectors in FAT
mov si,offset mboot_name ;Delete MBOOT.SYS
call delete_file
mov si,offset lastboot_name ;Delete LASTBOOT.BIN
call delete_file
mov cx,4
mov si,offset opsys_table ;Scan operating system table
xor bx,bx ; deleteing the MBOOTOS files
remove_2:
inc bl
cmp byte ptr [si],80h ;Is OS entry used?
jae remove_3
call delete_opsys
remove_3:
add si,NEXT_OSENTRY
loop remove_2
mov changed_flag,0
mov installed_flag,0 ;Clear install flag
call scroll_half ;Clear screen
clc ;Clear error flag
mov al,-1 ;Set terminate flag
remove_exit1:
ret
remove_error:
mov si,offset errmsg22
remove_error1:
stc
mov al,0
jmp short remove_exit1
main_remove endp
;--------------------------------------------------------------------
; EXIT - Updates changes to installed files and exits program.
;--------------------------------------------------------------------
exit_str0 db 15,14,"MultiBoot not installed.",0
exit_str1 db 15,16,"Do you wish to install MultiBoot?",0
exit_err1 db "Installed data incompatible with this version.",0
exit proc near
assume cs:code,ds:code
cmp installed_flag,0 ;If not installed, ask if
jne exit_1 ; prog should install.
mov si,offset exit_str0
call write_linenorm
mov al,1 ;Default Yes
mov si,offset exit_str1
call msg_box
cmp bl,1
jne exit_3
call main_install ;Install Multiboot
jc exit_4
jmp short exit_3
exit_1:
mov si,offset mboot_name ;Open the MBOOT.SYS file to
call make_filename ; write updated information.
mov si,dx ;Copy ptr to ASCIIZ filename
xor cx,cx
call set_attributes ;Clear file attributes
mov ax,3d02h
int 21h
jc exit_3
mov bx,ax ;Copy file handle
mov ax,4200h ;Move file ptr to boot table
mov dx,inst_data_ptr
xor cx,cx
int 21h
mov ah,40h ;Write boot data
mov dx,offset boot_data1
mov cx,inst_data_size
int 21h
mov ax,4200h ;Move file ptr to boot table
mov dx,inst_sess_ptr
xor cx,cx
int 21h
mov ah,40h ;Write boot session data
mov dx,offset boot_array
mov cx,inst_sess_size
int 21h
mov ax,4200h ;Move file ptr to os table
mov dx,inst_boot_ptr
xor cx,cx
int 21h
mov ah,40h ;Write boot op sys data
mov dx,offset opsys_table
mov cx,inst_boot_size
int 21h
mov ah,3eh ;Close file
int 21h
mov dx,si
mov cx,SYSFILE_ATTR
call set_attributes
exit_3:
mov al,-1 ;Set flag to end program
exit_4:
ret
exit endp
;--------------------------------------------------------------------
; QUIT - Quits program without changing installed files.
;--------------------------------------------------------------------
quit_msg db 20,15,"Do you wish to discard all changes made?",0
quit_msg1 db 20,9,"You have choosen to leave MultiBoot without",0
quit_msg2 db 17,10,"making your changes permanent. To make your",0
quit_msg3 db 17,11,"changes permanent, answer No, then select",0
quit_msg4 db 17,12,"Update and Exit MultiBoot on the Main Menu.",0
quit proc near
assume cs:code,ds:code
cmp changed_flag,0
je quit_1
mov si,offset quit_msg1 ;Tell user what he/she is
call write_linenorm ; doing.
mov si,offset quit_msg2
call write_linenorm
mov si,offset quit_msg3
call write_linenorm
mov si,offset quit_msg4
call write_linenorm
mov si,offset quit_msg
mov al,2 ;Set default to No.
call msg_box
mov al,0
cmp bl,2 ;See if No.
je quit_2
quit_1:
call scroll_half
mov al,-1 ;Set terminate prog flag
quit_2:
ret
quit endp
;--------------------------------------------------------------------
; JUMP MENU - Displays a menu then calls the routines pointed to in
; in the jump table.
; Entry: AL - Default selection
; SI - Offset of jump table
;--------------------------------------------------------------------
jump_menu proc near
mov bp,[si] ;Display main menu.
mov byte ptr [bp+MENU_SELECTED],al
push si
call menu
pop si
jnc jump_menu_2 ;Esc pressed -> Assume quit
jump_menu_1:
mov bl,[bp] ;BL = last choice
jump_menu_2:
or bl,bl ;If no cmd, assume quit.
je jump_menu_1 ;Convert menu choice to
shl bx,1 ; index into jump table of
add bx,si ; routines.
call scroll_half ;Clear lower half of screen.
call [bx] ;Call routine.
ret
jump_menu endp
;--------------------------------------------------------------------
; GET SESS NAME - Querys the user for a session name
; Entry: BL - Ptr to session entry
; Exit: CF - Set if Ctrl-C entered.
;--------------------------------------------------------------------
get_sess_name proc near
mov ax,offset local_add1 ;Compute entry into
call get_entry1 ; local table.
mov bp,bx ;Save ptr to table entry
call scroll_half ;Clear screen
mov dx,0806h ;Write header.
mov si,offset inst_text1
call write_line_at
mov di,bp ;Write session data to screen
mov dx,0a06h
call disp_session
mov si,offset add_str_msg1 ;Print message on how to
call write_linenorm ; return to add menu.
mov si,offset add_str4 ;Prompt user for Session name
call write_linenorm
mov dx,0e34h
mov al,offset auto1 - offset name1 - 1
call entry_box
jc get_sess_exit
mov si,bx
mov di,bp ;Copy title to local buffer.
rep movsb
mov byte ptr [di],0 ;Terminate string
mov dh,14
call clear_line
get_sess_exit:
ret
get_sess_name endp
;--------------------------------------------------------------------
; ADD FILE - Asks user for a filename and verifys its correctness.
; Entry: SI - Pointer to filename (CONFIG or AUTOEXEC)
;--------------------------------------------------------------------
add_file_str db 05,14,"Enter the file that will become the "
add_file_name db 12 dup (" ")
add_file_str1 db " file:",0
add_file_str2 db 05,14,"The file "
add_file_name0 db 12 dup (" ")
db "does not exist.",0
add_file_str3 db 05,16,"Do you want to copy the current "
add_file_name1 db 12 dup (" ")
db " file into this one?",0
add_file_err1 db "A filename must be entered",0
add_file_err2 db "The filename "
add_file_name2 db 12 dup (" ")
db " cannot be used",0
add_file_err3 db "Error creating file",0
add_file_err4 db "This file does not exist",0
add_file proc near
push si ;Save ptr to filename
mov dh,10
call clear_line
mov di,local_selection ;Write session data to screen
call disp_session
mov al," " ;Clear file names from strings
mov di,offset add_file_name
mov cx,12
rep stosb
mov di,offset add_file_name0
mov cx,12
rep stosb
mov di,offset add_file_name1
mov cx,12
rep stosb
mov di,offset add_file_name2
mov cx,12
rep stosb
pop bp ;Get ptr to filename
mov si,bp
mov di,offset add_file_name
call fn2asciiz
mov bx,cx
mov byte ptr [bx+si]," " ;Erase zero
push si ;Copy filename to other
mov di,offset add_file_name1 ; messages
push cx
rep movsb
pop cx
pop si
mov di,offset add_file_name2
rep movsb
add_file_1:
mov dh,14 ;Clear line for query.
call clear_line
mov si,offset add_file_str ;Assemble prompt message using
call write_linenorm ; destination filename
mov si,offset add_file_str1 ; provided.
call write_linenorm
mov si,offset add_str_msg1 ;Print message on how to
call write_linenorm ; return to add menu.
mov dx,0e3ch ;Get filename max char = 12
mov al,12
call entry_box
pushf
mov dh,22 ;Erase ctl-break message
call clear_line
popf
jnc add_file_11
jmp add_file_4
add_file_11:
or cx,cx ;If zero length string, error
mov si,offset add_file_err1
je add_file_error
mov si,cx
mov byte ptr [bx+si],0 ;Terminate name with zero
push cx
mov si,bx
mov di,offset temp_buff
call asciiz2fn
mov di,bp ;Make sure destination name
mov cx,11 ; not used.
repe cmpsb
pop cx
jne add_file_2
mov si,offset add_file_err2 ;Can't use dest filename
add_file_error:
call write_error
jmp short add_file_1
add_file_2:
mov si,offset temp_buff ;Create filename from 8.3
call make_filename ; format.
mov ax,3d00h ;Open file, read only
int 21h
jnc add_file_3
mov si,offset temp_buff ;Add filename to error msg
mov di,offset add_file_name0
call fn2asciiz
mov bx,cx
mov byte ptr [bx+si]," " ;Erase terminating zero
mov si,offset add_file_err4 ;Indicate to the user that
call write_error ; the file can't be found.
mov si,bp ;Get destination file
call find_file
jc add_file_1 ;If no file, skip copy question
mov dh,14 ;File does not exist, prompt
call clear_line ; user for choices.
mov si,offset add_file_str2
call write_linenorm
mov al,1 ;Set default answer
mov si,offset add_file_str3 ;See if user wants to copy
call msg_box ; the current autoexec or
mov dh,14 ; config file to this one.
call clear_line
cmp bl,1 ;If not Yes, skip copy.
je add_file_21
jmp add_file_1
add_file_21:
mov si,bp
mov di,offset temp_buff+40
call make_filename
mov di,offset filename_buff ;Copy autoexec or config to
call copy_file ; new filename
mov si,offset add_file_err3
jc add_file_error
add_file_3:
mov si,offset temp_buff ;Point SI to new filename
clc
add_file_4:
ret
add_file endp
;--------------------------------------------------------------------
; GET SESSION - Displays a session menu.
; Entry: AL - Default session.
; Exit: BX - Session number selected.
;--------------------------------------------------------------------
get_sess_str db 20,7,"Select Session",0
get_session proc near
mov bx,1 ;If only one session, don't
cmp session_count,1 ; ask user to pick.
ja get_session_1
jmp short get_session_3
get_session_1:
mov bp,offset boot_menu
get_session_2:
push ax
call scroll_half ;Clear screen.
mov si,offset get_sess_str ;Display message
call write_linenorm
pop ax
mov [bp+MENU_SELECTED],al ;Set default
mov word ptr [bp+MENU_TIMEOUT],0
call menu
get_session_3:
pushf ;Carry indicates <esc> pressed
call scroll_half
popf
ret
get_session endp
;--------------------------------------------------------------------
; GET OSTYPE - Prompts the user to select an operating system.
; Exit: BL - OS selection
;--------------------------------------------------------------------
os_menu_str1 db 05,14,"Select Operating System",0
os_menu db 4,1 ;Number of choices, Selected
db 30,22 ;Location of "Choices" prompt
dw 0 ;Timeout value
db 0,0 ;Col, Row of Timeout string
db 25,17 ;Column, Row of menu item
dw offset os_name1 ;Offset of menu text
db 25,18
dw offset os_name2
db 25,19
dw offset os_name3
db 25,20
dw offset os_name4
get_ostype proc near
mov si,offset os_menu_str1 ;Prompt user for the
call write_linenorm ; operating system
mov bp,offset os_menu ;Operating system menu
call menu
pushf
mov cx,0e00h ;Clear screen
mov dx,1950h
call scroll_block
xor di,di
popf ;If <esc> no choice made
jc get_ostype_exit
call get_os_entry
clc
get_ostype_exit:
ret
get_ostype endp
;--------------------------------------------------------------------
; MAKE FILENAME - Adds drive and directory stuff to 8.3 filename.
; Entry: SI - Pointer to filename
; Exit: SI = DX - Pointer to filename
;--------------------------------------------------------------------
make_filename proc near
push cx
push di
mov di,offset filename_buff
push di
mov al,drive_letter ;Copy drive letter
stosb
mov ax,"\:" ;Add DOS dir stuff
stosw
call fn2asciiz ;Append filename
pop si
mov dx,si ;Copy pointer to filename
pop di
pop cx
ret
make_filename endp
;--------------------------------------------------------------------
; READ FILE - Opens a file, reads the data, and closes the file.
; Entry: DS:DX - Pointer to source ASCIIZ filename
; ES:SI - Pointer to data buffer
; Exit: CX - Bytes read
;--------------------------------------------------------------------
read_file proc near
call set_crit_vec ;Set crit vec to int routine
mov ax,3d00h ;Open file, read only
int 21h
jc read_file_exit
mov bx,ax ;Copy file handle
push ds ;Read file into data buffer
push es
pop ds
mov dx,si
mov cx,65013 ;Buffer size
mov ah,3fh ;Read file
int 21h
mov cx,ax ;Save bytes read
pop ds
jc read_file_exit
mov ah,3eh ;Close file
int 21h
read_file_exit:
call reset_crit_vec ;Restore critical error vec
ret
read_file endp
;--------------------------------------------------------------------
; WRITE FILE - Creates a file and writes data to the file
; Entry: AX - Attributes for destination file
; CX - Size of data
; DS:DX - Pointer to desination ASCIIZ filename
; ES:SI - Pointer to data
;--------------------------------------------------------------------
write_file proc near
push cx ;Save size of data
call set_crit_vec ;Set crit vec to int routine
mov cx,ax ;Copy attributes
mov ah,3ch ;Create file.
int 21h
mov bx,ax ;Copy file handle
pop cx ;Restore data size
jc write_file_exit
push ds
push es
pop ds
mov dx,si ;Copy pointer to data
mov ah,40h ;Write file
int 21h
pop ds
jc write_file_exit
mov ah,3eh ;Close file
int 21h
write_file_exit:
call reset_crit_vec ;Restore critical error vec
ret
write_file endp
;--------------------------------------------------------------------
; READ ABSOLUTE - Reads sectors from the disk.
; Entry: AL - Letter of drive to read
; CX - Number of sectors to read.
; SI,DX - Sector to start read (SI only used on huge disks)
; DS:BX - Pointer to data buffer.
;--------------------------------------------------------------------
read_abs_hstruc = $ ;Needed for >32M disks
read_abs_start dd 0 ;Starting sector
read_abs_cnt dw 0 ;Number of sectors to read
read_abs_dbp dd 0 ;Data buffer ptr
read_absolute proc near
push bx
push cx
push ds
call set_crit_vec ;Set crit vec to int routine
call huge_disk_check
jc read_abs_2
je read_abs_1
push ds ;Save ptr to data buffer
push bx
push cs
pop ds
mov bx,offset read_abs_hstruc
mov [bx],dx ;More than 64K sectors
mov [bx+2],si ; -> huge disk uses a
mov [bx+4],cx ; different format
pop [bx+6] ; than std int 25h.
pop [bx+8]
mov cx,-1
read_abs_1:
sub al,'A' ;Convert to hex (0 base)
int 25h ;DOS Absolute Disk Read
pop bx ;Clean off old flags
cld
read_abs_2:
call reset_crit_vec ;Restore critical error vec
pop ds
pop cx
pop bx
ret
read_absolute endp
;--------------------------------------------------------------------
; WRITE ABSOLUTE - Writes sectors to the disk.
; Entry: AL - Letter of drive to write
; CX - Number of sectors to write
; SI,DX - Sector to start write (SI only used on huge disks)
; DS:BX - Pointer to data buffer.
;--------------------------------------------------------------------
write_absolute proc near
push bx
push cx
push ds
call set_crit_vec ;Set crit vec to int routine
call huge_disk_check
jc write_abs_2
je write_abs_1
push ds ;Save data buffer pointer
push bx
push cs
pop ds
mov bx,offset read_abs_hstruc
mov [bx],dx ;More than 64K sectors
mov [bx+2],si ; -> huge disk uses a
mov [bx+4],cx ; different format
pop [bx+6] ; than std int 26h.
pop [bx+8]
mov cx,-1
write_abs_1:
sub al,'A' ;Convert to hex (0 based)
int 26h ;DOS Absolute Disk Write
pop bx ;Clean off old flags
cld
write_abs_2:
call reset_crit_vec ;Restore critical error vec
pop ds
pop cx
pop bx
ret
write_absolute endp
;--------------------------------------------------------------------
; HUGE DISK CHECK - Checks if disk is greater than 32 Meg
; Entry: AL - Disk to check
; Exit: ZF - Clear if > 32 Meg disk
; CF - Set if error
; DI - Sectors per cluster
;--------------------------------------------------------------------
last_disk_read db -1
last_disk_huge db 0
last_disk_spc dw 0
huge_disk_check proc near
push ax
push bx
push cx
push dx
cmp al,last_disk_read ;Save last disk checked, if
jne huge_disk_check_1 ; same as last disk, just
mov di,last_disk_spc ; get saved answer.
cmp last_disk_huge,0
jmp short huge_disk_check_3
huge_disk_check_1:
mov last_disk_read,al
mov last_disk_huge,0
mov dl,al ;Copy disk number
sub dl,40h ;Convert ASCII to hex (1 base)
mov ah,36h ;DOS Get Free disk space
int 21h
cmp ax,-1
jne huge_disk_check_2
mov last_disk_read,-1
jmp short huge_disk_check_4
huge_disk_check_2:
mov di,ax ;Save sectors per cluster
mov last_disk_spc,di
mul dx
or dx,dx ;See if more than 64K sectors
je huge_disk_check_3
mov last_disk_huge,1
huge_disk_check_3:
clc
huge_disk_check_4:
pop dx
pop cx
pop bx
pop ax
ret
huge_disk_check endp
;--------------------------------------------------------------------
; COPY FILE - Copies a file
; Entry: DX - Pointer to source ASCIIZ filename
; DI - Pointer to destination ASCIIZ filename
;--------------------------------------------------------------------
copy_file proc near
push es
les si,databuff_ptr
call read_file
jc copy_file_exit
mov dx,di ;Point to new file name
xor ax,ax ;Normal attributes
call write_file
copy_file_exit:
pop es
ret
copy_file endp
;--------------------------------------------------------------------
; DELETE FILE - Deletes file
; Entry: SI - Pointer to filename in 8.3 format
;--------------------------------------------------------------------
delete_file proc near
push cx
push si
call make_filename ;Convert to ASCIIZ
xor cx,cx
call set_attributes
mov ah,41h ;DOS Delete File
int 21h
pop si
pop cx
ret
delete_file endp
;--------------------------------------------------------------------
; SET ATTRIBUTES - Sets file attribute flags.
; Entry: CX - file attributes
; DX - pointer to ASCIIZ filename.
;--------------------------------------------------------------------
set_attributes proc near
mov ax,4301h ;DOS Set Attributes
int 21h
ret
set_attributes endp
;--------------------------------------------------------------------
; MAKE BOOTFILE - Writes the boot record data in the data buffer
; to a file on the disk.
; Entry: SI - Destination filename in 8.3 format
;--------------------------------------------------------------------
make_bootfile proc near
push es
les si,databuff_ptr ;Get ptr to boot record
mov ax,SYSFILE_ATTR ;Get attributes
mov cx,512 ;Boot file size
call write_file
pop es
ret
make_bootfile endp
;--------------------------------------------------------------------
; GET BOOTREC - Reads the boot record into the data buffer.
; Entry: AL - Letter of drive to read
;--------------------------------------------------------------------
get_bootrec proc near
mov cx,1 ;Read 1 sector
xor dx,dx ;Read 1st sector
xor si,si
push ds
lds bx,databuff_ptr ;Get ptr to data buffer
call read_absolute ;DOS Absolute Disk Read
pop ds
ret
get_bootrec endp
;--------------------------------------------------------------------
; PUT BOOTREC - Writes the boot record with data from the data buffer.
; Entry: AL - Drive letter to write
; DS:BX - Segment:Offset of boot record to write.
;--------------------------------------------------------------------
put_bootrec proc near
mov cx,1 ;Write 1 sector
xor dx,dx ;Write 1st sector
xor si,si
call write_absolute ;DOS Absolute Disk Write
ret
put_bootrec endp
;--------------------------------------------------------------------
; COPY BPB - Copies a BIOS parameter block.
; Entry: AL - 0 = to MBOOT boot rec, 1 = from MBOOT bootrec
;--------------------------------------------------------------------
copy_bpb proc near
push cx
push ds
push es
les di,databuff_ptr ;Offset of boot rec BPB
add di,11
mov si,10bh ;Offset of MBOOT BPB
or al,al
jne copy_bpb_1
xchg si,di ;Exchange pointers.
push es
push ds
pop es
pop ds
copy_bpb_1:
mov cx,32 ;Copy BPB
rep movsb
or al,al
je copy_bpb_2
cmp cs:[drive_letter],"C"
jb copy_bpb_2
cmp byte ptr es:[1fdh],0
jne copy_bpb_2
mov byte ptr es:[1fdh],80h
copy_bpb_2:
pop es
pop ds
pop cx
ret
copy_bpb endp
;--------------------------------------------------------------------
; COPY OS NAME - Reads the operating system name from the OEM field
; of the boot record.
; Entry: AL - Operating system type.
; BL - Operating system number.
;--------------------------------------------------------------------
copy_os_name proc near
call get_os_entry ;Get index into the os table
mov word ptr [di+OPSYS_TYPE],cx
push di
push si
push ds
lds si,databuff_ptr ;Copy the OEM name to the
add si,3 ; field pointed to by
mov cx,8 ; DI.
rep movsb
pop ds
pop si
pop di
add di,9
mov si,offset ibmbio_name ;Copy the proper names of the
cmp al,1 ; os files to the os table.
jb copy_os_name_1
ja copy_os_name_2
mov si,offset iosys_name
copy_os_name_1:
mov cx,22 ;Copy both names at the same
rep movsb ; time.
copy_os_name_2:
ret
copy_os_name endp
;--------------------------------------------------------------------
; GET OPSYS - Gets the operating system files from a disk
; Entry: AL - Drive letter to read operating system
; Exit: CF - Set if error
; AL - Return code:
; 0 - PC DOS 3 - MultiBoot 6 - Read error
; 1 - MS DOS 4 - Unbootable 7 - OS too large
; 2 - OS/2 disk 5 - Unknown
; AH - 1 if OS/2 system on disk
; CX - Number of consecutive clusters used by DOS
; DX - Number of consecutive clusters used by IO.SYS
; CF - Set if error
; opsys_ostype, iosys_size, doscom_size updated.
;--------------------------------------------------------------------
get_opsys proc near
mov bl,drive_letter
push bx
mov drive_letter,al
call check_os ;See what type of OS loaded
mov opsys_ostype,bx ; on disk.
mov bp,offset ibmbio_name
cmp al,1 ;If PC DOS use different
ja get_opsys_error1 ; names from MS DOS
jb get_opsys_1
mov bp,offset iosys_name
get_opsys_1:
push ax
push cx
push dx
mov iosys_size,0
mov si,bp ;Copy ptr to first name
call make_filename
push es
les si,databuff_ptr
add si,512 ;Skip past boot data
call read_file
pop es
mov al,6
jc get_opsys_error
mov al,7 ;Error, os file too big
cmp cx,65013
jae get_opsys_error
mov iosys_size,cx
mov doscom_size,0
mov si,bp ;Copy ptr to first name
add si,11 ;Point to second name
call make_filename
push es
les si,databuff1_ptr
call read_file
pop es
mov al,6
jc get_opsys_error
mov al,7 ;Error, os file too big
cmp cx,65013
jae get_opsys_error
mov doscom_size,cx ;Save DOSCOM file size
pop dx
pop cx
pop ax
clc
get_opsys_exit1:
mov bp,ax
pop ax
mov drive_letter,al ;Restore target disk letter
mov ax,bp
ret
get_opsys_error:
add sp,6 ;Clean off stack
get_opsys_error1:
stc
jmp short get_opsys_exit1
get_opsys endp
;--------------------------------------------------------------------
; CHECK SIZE - Compares the size of two numbers to the nearest sector
; Entry: BX - File 1 size in bytes
; CX - File 2 size in bytes
; Exit: Flags set from compare
;--------------------------------------------------------------------
check_size proc near
push ax
mov ax,bx
xor dx,dx ;Clear high word
mov bx,512 ;Div by sector size
div bx
xchg ax,cx ;Get second number
xor dx,dx
div bx ;Div second number
cmp ax,cx ;Compare results
pop ax
ret
check_size endp
;--------------------------------------------------------------------
; PUT OPSYS - Saves the operating system to files on the disk
; Entry: BL - Operating system number
; BH - 1 = Make bootfile name LASTBOOT.BIN
;--------------------------------------------------------------------
put_opsys proc near
push bp
call make_os_names ;Generate names for files
push si
or bh,bh
je put_opsys_1
mov si,offset lastboot_name
put_opsys_1:
call make_filename
xor cx,cx
call set_attributes
call make_bootfile ;Write boot rec to file.
pop si
add si,11 ;Point to iosys name
mov bp,si
call make_filename
xor cx,cx
call set_attributes
push es
les si,databuff_ptr ;Load ptr to SYS file data
add si,512
mov cx,iosys_size ;Set size
mov ax,SYSFILE_ATTR ;Set attributes
call write_file ;Write IO.SYS file
pop es
jc put_os_exit
mov si,bp
add si,11 ;Point to doscom name
call make_filename
xor cx,cx
call set_attributes
push es
les si,databuff1_ptr
mov cx,doscom_size ;Set size
mov ax,SYSFILE_ATTR ;Set attributes
call write_file ;Write MSDOS.COM file
pop es
put_os_exit: clc
pop bp
ret
put_opsys endp
;--------------------------------------------------------------------
; DELETE OPSYS - Deletes the MBOOT operating system files from the disk.
; Entry: BL - Operating system number
;--------------------------------------------------------------------
delete_opsys proc near
push si
push bx
call make_os_names ;Get names of op sys files
call delete_file ;Delete boot rec file
add si,11
call delete_file ;Delete IO.SYS file
add si,11
call delete_file ;Delete MSDOS.COM file
pop bx
call get_os_entry
mov byte ptr [di],80h ;Delete entry in opsys table
pop si
ret
delete_opsys endp
;--------------------------------------------------------------------
; CHECK OS - Reads the boot record to determine the type of operating
; system currently loaded.
; Exit: AL - Type of operating system loaded:
; 0 - PC DOS 2 - OS/2 4 - Not a bootable disk
; 1 - MS DOS 3 - MultiBoot 5 - Unknown OS type
; AH - 1 if OS/2 system files are loaded (if AL = 0, 1, or 2)
; BX - DOS System file configuration:
; 20 = Consec files, sectors
; 30 = IO.SYS Consec. MSDOS.SYS not consec
; 40 = IO.SYS not Consec
; CX - Number of consecutive clusters used by DOS
; DX - Number of consecutive clusters used by IO.SYS
;--------------------------------------------------------------------
check_os proc near
mov al,drive_letter
call get_bootrec ;Load boot record.
mov ax,00ffh
jc check_os_exit ;If error loading, exit
mov di,offset mboot_name ;Check if Multiboot is
call find_filename ; installed on drive.
mov ax,3 ;Multiboot installed
jnc check_os_exit
xor bp,bp
mov di,offset os2ldr_name ;See if OS/2 disk
call find_filename
mov ax,2 ;OS/2 disk
jnc check_os_exit
mov di,offset ibmbio_name ;See if PC DOS disk
call find_filename
jnc check_os_1
inc bp
mov di,offset iosys_name ;See if MS DOS disk
call find_filename
mov ax,5 ;Error, unknown DOS type
jc check_os_exit
check_os_1:
mov ax,bp
call get_sys_size ;Get size of DOS file area
mov bx,ax ; on disk.
mov ax,4
jc check_os_exit ;CF=1 not bootable.
check_os_2:
push bx ;Save DOS config
push cx ;Save DOS size
push dx ;Save IO.SYS size
mov si,offset os2ldr_name ;See if OS/2 system files
call find_first ; on disk. Start with OS2LDR
jc check_os_3
mov si,offset os2knl_name ;Look for OS2KRNL
call find_first
jc check_os_3
mov si,offset os2boot_aname ;Look for \OS2\SYSTEM\BOOT.OS2
mov al,drive_letter
mov [si],al
call find_first1
jc check_os_3
or bp,0100h ;Set OS/2 found flag
check_os_3:
mov ax,bp ;Get OS type
pop dx ;Get IO.SYS size
pop cx ;Get DOS size
pop bx ;Get DOS config
check_os_exit:
ret
check_os endp
;--------------------------------------------------------------------
; GET SYS SIZE - Computes the number of consecutive clusters assigned
; to the system files at the beginning of the disk.
; Entry: AL - Type of operating system loaded:
; 0 - PC DOS 1 - MS DOS
; The Boot record for the desired disk must be in the data
; buffer.
; Exit: AX - DOS System file configuration:
; 20 = Consec files, sectors
; 30 = IO.SYS consec. MSDOS.SYS not consec
; 40 = IO.SYS not consec
; CX - Number of consecutive clusters
; DX - Number of consecutive clusters used by IO.SYS
; CF - Set on error
;--------------------------------------------------------------------
sys_size_os db 0
sys_size_bio dw 0
sys_size_dos dw 0
get_sys_size proc near
push bp
mov sys_size_os,al
call get_disk_ptrs ;Compute disk pointers.
mov dx,word ptr root_pointer
mov si,word ptr root_pointer[2]
mov cx,1 ;Read only one sector of root
lds bx,databuff_ptr ;Use buffer past boot rec
add bx,512
mov al,cs:drive_letter
call read_absolute ;Read 1st part of root dir
mov di,offset ibmbio_name
cmp cs:sys_size_os,0 ;Get proper system file names
je get_sys_size_2 ; for DOS.
mov di,offset iosys_name
get_sys_size_2:
mov si,bx ;Copy ptr to start of root
mov cx,11
repe cmpsb ;See if first file is IO.SYS
je get_sys_size_3
get_sys_size_err:
stc
jmp get_sys_size_exit1
get_sys_size_3:
mov ax,[bx+1ah] ;Get starting cluster
cmp ax,2 ;See if starts in 1st cluster
je get_sys_size_4
xor dx,dx ;No free clusters
xor cx,cx
mov ax,50h
jmp get_sys_size_exit1
get_sys_size_4:
mov cs:sys_size_bio,ax
add si,21
mov cx,11
repe cmpsb ;See if 2nd file is MSDOS.SYS
jne get_sys_size_err
mov ax,[bx+3ah] ;Get starting cluster
mov cs:sys_size_dos,ax
mov dx,word ptr cs:fat_pointer
mov si,word ptr cs:fat_pointer[2]
mov al,cs:drive_letter
mov cx,4 ;Read four sectors
call read_absolute ;Read FAT
mov ax,ds
push cs
pop ds
push fat_seg_low ;Save FAT ptr for installed
add ax,20h ; code.
mov fat_seg_low,ax ;Point to loaded FAT table
mov bx,sys_size_bio
mov bp,offset temp_buff
call get_fat_chain ;Get consec clusters
pushf
xor ax,ax
mov al,sec_per_cluster ;Convert cluster count into
mul cx ; sector count
mov di,ax
xchg cx,ax
popf
mov ax,40h
jc get_sys_size_exit ;If non-consecutive, DOS 4
inc bx
mov si,bx ;Save ending cluster
mov bx,sys_size_dos
cmp si,bx ;If IO.SYS and MSDOS.SYS are
mov ax,30h ; not consecutive, DOS 3.
jne get_sys_size_exit
call get_fat_chain
pushf
xor ax,ax ;Convert cluster count into
mov al,sec_per_cluster ; sector count.
mul cx
mov cx,ax
add cx,di ;Add sector sizes
mov dx,di ;Copy IO.SYS sector size
popf
mov ax,30h
jc get_sys_size_exit
mov ax,20h ;Both consecutive, DOS 2
get_sys_size_exit:
push ax
xchg ax,dx
cwd
div targ_sec_per_cluster ;Convert sectors to clusters
or dx,dx ; on target disk.
je get_sys_size_e1
inc ax
get_sys_size_e1:
push ax
xchg ax,cx
cwd
div targ_sec_per_cluster
or dx,dx
je get_sys_size_e2
inc ax
get_sys_size_e2:
xchg ax,cx
pop dx
pop ax
pop fat_seg_low
clc
get_sys_size_exit1:
push cs
pop ds
pop bp
ret
get_sys_size endp
;--------------------------------------------------------------------
; FIXUP FAT - Removes the bad cluster entries placed by the boot
; extension prog.
; Entry: Boot sector loaded in the 1st 512 bytes of the data buffer.
; Exit: CF - Set if error
;--------------------------------------------------------------------
fixup_fat proc near
call get_disk_ptrs
mov dx,word ptr cs:fat_pointer
mov si,word ptr cs:fat_pointer[2]
mov al,cs:drive_letter
lds bx,databuff_ptr
add bx,512
mov cx,4 ;Read four sectors
call read_absolute ;Read FAT
jc fixup_fat_exit
mov ax,ds
push cs
pop ds
push fat_seg_low ;Save FAT ptr for installed
add ax,20h ; code.
mov fat_seg_low,ax ;Point to loaded FAT table
call clean_fat ;Remove bad cluster flags
pop fat_seg_low ;Restore FAT segment
push ds
lds bx,databuff_ptr ;Write FAT table to disk
add bx,512
mov dx,word ptr cs:fat_pointer ;Write FAT tables
mov si,word ptr cs:fat_pointer[2]
xor cx,cx
mov bp,cx
mov cl,ds:number_of_fats
fixup_fat_1:
push cx
mov al,cs:drive_letter
mov cx,4 ;Write four sectors
call write_absolute ;Write FAT
pop cx
jc fixup_fat_2
add dx,ds:sec_per_fat ;Point to next FAT
adc si,0
loop fixup_fat_1
fixup_fat_2:
pop ds
fixup_fat_exit:
ret
fixup_fat endp
;--------------------------------------------------------------------
; GET DISK PTRS - Computes the logical sector numbers of the FAT and
; root directorys.
; Entry: Boot sectors loaded in the 1st 512 bytes of the data buffer.
; Exit: CF - Set if error
;--------------------------------------------------------------------
fat_pointer dd 0
root_pointer dd 0
get_disk_ptrs proc near
push bp
push ds
push cs
pop es
lds si,databuff_ptr ;Copy the BPB from the
mov di,offset temp_buff ; boot record.
mov bp,di
mov cx,40
rep movsb
pop ds
call get_fattype ;See if FAT 12 or 16 bit
xor ax,ax
mov al,number_of_fats ;Compute the sector of the
mul sec_per_fat ; root directory and FAT
mov dx,reserved_sec ; table.
xor si,si
mov word ptr fat_pointer,dx
mov word ptr fat_pointer[2],si
add dx,ax ;Add size of FAT to get ptr
adc si,0 ; to root directory
mov word ptr root_pointer,dx
mov word ptr root_pointer[2],si
pop bp
ret
get_disk_ptrs endp
;--------------------------------------------------------------------
; FIND FIRST - Searches the disk for a file.
; Entry: SI - Pointer to an 8.3 filename
; Exit: CF - Clear if found
;
; FIND FIRST1 - Searches the disk for a file.
; Entry: SI - Pointer to an ASCIIZ filename
; Exit: CF - Clear if found
;--------------------------------------------------------------------
find_first proc near
call make_filename ;Convert to ASCIIZ filename
mov si,dx
find_first1:
mov ah,1ah ;Insure that DTA set to
mov dx,DTA_OFFSET ; empty space in PSP
int 21h
push cx
mov dx,si
mov ah,4eh ;Find file
mov cx,6 ;Inc system and hidden files
int 21h
pop cx
ret
find_first endp
;--------------------------------------------------------------------
; FIND FILENAME - Searches a loaded boot record for a filename
; Entry: DI - Pointer to 8.3 filename
; Exit: CF - Clear if found
;--------------------------------------------------------------------
find_filename proc near
push di
push ds
lds si,databuff_ptr ;Search boot record for
mov bx,11 ; the filename pointed
mov cx,512 ; to by DI.
call find_string
pop ds
pop di
ret
find_filename endp
;--------------------------------------------------------------------
; FIND STRING - Searches a buffer for a specified string
; Entry: DS:SI - Pointer to buffer
; ES:DI - Pointer to string to find
; BX - Length of string
; CX - Length of buffer
;--------------------------------------------------------------------
find_string proc near
push bp
push dx
mov bp,si ;Compute end of buffer
add bp,cx
mov dx,di ;Save ptr to string
find_string_1:
mov di,dx ;Get ptr to string
mov ax,si
mov cx,bx ;Get length of string
repe cmpsb ;Check string
je find_string_exit
mov si,ax
inc si ;Point to next char in buffer
lea di,[si+bx] ;Determine if we are at the
cmp di,bp ; end of the buffer.
jbe find_string_1
stc
find_string_exit:
pop dx
pop bp
ret
find_string endp
;--------------------------------------------------------------------
; SET CRIT VEC - Sets the critical error vector to an internal routine
; to avoid the abort, retry, ignore message.
;--------------------------------------------------------------------
set_crit_vec proc near
push ax
push bx
push dx
push ds
push es
mov ax,3524h ;Get crititcal error vector
int 21h
mov word ptr crit_vec,bx ;Save vector
push cs
pop ds
mov word ptr crit_vec[2],es
mov dx,offset crit_error ;Set to internal routine.
mov ax,2524h
int 21h
pop es
pop ds
pop dx
pop bx
pop ax
ret
set_crit_vec endp
;--------------------------------------------------------------------
; RESET CRIT VEC - Resets the critical error vector to its original
; state.
;--------------------------------------------------------------------
reset_crit_vec proc near
pushf
push ax
push dx
push ds
lds dx,crit_vec ;Get old vector
mov ax,2524h ;Set vector
int 21h
pop ds
pop dx
pop ax
popf
ret
reset_crit_vec endp
;--------------------------------------------------------------------
; SET CTLC VEC - Sets the control C vector to an internal routine
; to handle the problem in a polite manner.
;--------------------------------------------------------------------
set_ctlc_vec proc near
push ax
push bx
push dx
push ds
push es
mov ax,3523h ;Get ctl-c vector
int 21h
mov word ptr ctlc_vec,bx ;Save vector
push cs
pop ds
mov word ptr ctlc_vec[2],es
mov dx,offset ctlc_error ;Set to internal routine.
mov ax,2523h
int 21h
pop es
pop ds
pop dx
pop bx
pop ax
ret
set_ctlc_vec endp
;--------------------------------------------------------------------
; RESET CTLC VEC - Resets the control C vector to its original
; state.
;--------------------------------------------------------------------
reset_ctlc_vec proc near
push dx
push ds
lds dx,ctlc_vec ;Get old vector
mov ax,2523h ;Set vector
int 21h
pop ds
pop dx
ret
reset_ctlc_vec endp
;--------------------------------------------------------------------
; CHK MBOOT DISK - Reads the time stamp from the installed mboot.sys
; code to verify proper disk is in drive.
;--------------------------------------------------------------------
chk_mboot_disk proc near
push ax
push cx
push dx
cmp installed_flag,0 ;If not installed, skip
je chk_mboot_disk_exit ; check.
mov si,offset mboot_name ;Open the MBOOT.SYS file to
call make_filename ; read the time stamp.
mov ax,3d00h
int 21h
jc chk_mboot_disk_exit
mov bx,ax ;Copy file handle
mov ax,4200h ;Move file ptr
mov dx,inst_data_ptr
add dx,offset time_stamp - offset boot_data1
xor cx,cx
int 21h
mov ah,3fh ;Read time stamp
mov dx,offset temp_buff
mov cx,4
int 21h
mov ah,3eh ;Close file
int 21h
mov cx,word ptr temp_buff ;Compare time stamps
mov dx,word ptr temp_buff[2]
cmp cx,word ptr time_stamp
jne chk_mboot_disk_error
cmp dx,word ptr time_stamp[2]
je chk_mboot_disk_exit
chk_mboot_disk_error:
stc
chk_mboot_disk_exit:
pop dx
pop cx
pop ax
ret
chk_mboot_disk endp
;--------------------------------------------------------------------
; DISP SETTINGS - Displays settings for all sessions.
; Entry: DI - Pointer to first entry data
; DH - Row to start display
;--------------------------------------------------------------------
disp_settings proc near
mov dx,0806h ;Write header.
mov si,offset inst_text1
call write_line_at ;Write string
add dh,2
mov cx,4 ;4 Sessions
mov bh,1 ;Set session counter
disp_settings_1:
push di
mov al,bh ;Print session number
mov dl,2
call printnum ;Write number
mov dl,5
cmp byte ptr [di+OSTYPE_OFFSET],0 ;See if session disabled
jne disp_settings_2
mov si,offset unused_text ;Point to unused string
call write_line_at ;Write string
jmp short disp_settings_3
disp_settings_2:
call disp_session
cmp bh,boot_default ;If this selection is the
jne disp_settings_3 ; default selection, print
mov dl,74 ; default indication.
mov si,offset default_str
call write_line_at ;Write string
disp_settings_3:
pop di
add di,NEXT_ENTRY
inc dh ;Next row
inc bh ;Next number
loop disp_settings_1
ret
disp_settings endp
;--------------------------------------------------------------------
; DISP SESSION - Displays settings for one entry.
; Entry: DI - Pointer to entry data
; DH - Row to start display
;--------------------------------------------------------------------
disp_session proc near
push bx
push cx
push dx
push bp
mov bp,di ;Copy pointer to data
mov dl,5 ;Set starting column
mov si,bp ;Get ptr to name
cmp byte ptr [si],80h ;If unused, don't print
jae disp_session_1
call write_line_at ;Write string
lea si,[bp+AUTO_OFFSET] ;Get ptr to autoexec name
mov dl,29
call print_fn ;Print AUTOEXEC name
mov dl,46
lea si,[bp+CONFIG_OFFSET] ;Get ptr to config name
call print_fn ;Print CONFIG name
xor bx,bx ;Get op sys type. If not
or bl,[bp+OSTYPE_OFFSET] ; defined, don't print.
jz disp_session_1
call get_os_entry ;Get offset into os table
mov si,di
mov di,offset key_buffer ;First copy to buffer, then
push di ; terminate string with zero.
mov cx,8
rep movsb
mov byte ptr [di],0
pop si
mov dl,63
call write_line_at ;Write string
disp_session_1:
pop bp
pop dx
pop cx
pop bx
ret
disp_session endp
;--------------------------------------------------------------------
; MSG BOX - Displays a string and prompts the user for a Yes/No answer.
; Entry: SI - Pointer to string. 1st two bytes are the cursor location.
; Exit: BL - User response, 1 = yes, 2 = no.
;--------------------------------------------------------------------
msg_box proc near
push bp
push ax
call write_linenorm ;Write prompt string
pop ax
mov bp,offset yesno_menu ;Yes / No menu.
mov [bp+MENU_SELECTED],al ;Set default
call menu
mov cx,1000h ;Clear yes/no menu.
mov dx,1980h
call scroll_block
pop bp
ret
msg_box endp
;--------------------------------------------------------------------
; CONFIRM QUIT - Asks the user to confirm quit request.
; Exit: ZF - Set, quit confirmed.
;--------------------------------------------------------------------
confirm_quit proc near
mov cx,1000h ;Make room for question
mov dx,1980h
call scroll_block
mov si,offset confirm_msg
mov al,2 ;Set default to No.
call msg_box
cmp bl,1 ;See if answer Yes.
ret
confirm_quit endp
;--------------------------------------------------------------------
; GET NUMBER - Querys the user for a number.
; Entry: AL - Number of characters allowed.
; DX - Cursor location for entry box.
; Exit: AX - Number returned by the user entered.
; CF - Set if user returned an invalid number.
;--------------------------------------------------------------------
get_number proc near
call entry_box
jc get_number_exit
xor ax,ax ;Convert ascii number into
xor dx,dx ; hex.
mov si,10 ;Base 10
get_number_loop:
mul si ;Mul current num by base
mov dl,[bx] ;Get character
sub dl,30h ;Convert to hex from ASCII
jb get_number_err
cmp dl,9
ja get_number_err
add ax,dx ;Add to total.
inc bx ;Move to next char
loop get_number_loop
clc
get_number_exit:
ret
get_number_err:
stc
jmp short get_number_exit
get_number endp
;-----------------------------------------------------------------------------
; CTLC ERROR - Ctl-C routine to allow polite control C action.
;-----------------------------------------------------------------------------
ctlc_error proc far
cmp ctlc_return,0
je ctlc_1
mov sp,ctlc_stack
jmp [ctlc_return]
ctlc_1:
iret
ctlc_error endp
;--------------------------------------------------------------------
; ENTRY BOX - Querys user for one line of input.
; Entry: AL - Number of characters allowed.
; DX - Cursor location for entry box.
; Exit: BX - Pointer to buffer containing the user response.
; CX - length of response.
;--------------------------------------------------------------------
entry_box proc near
push ax
xor bx,bx
mov ah,2 ;Set cursor position
call vidint
pop ax
mov bx,offset key_buffer
inc al
mov [bx],al ;Set buffer size
mov dx,bx
mov ax,offset entry_box_error
mov ctlc_stack,sp
mov ctlc_return,ax
mov ah,0ah ;DOS buffered read
int 21h
inc bx ;Point to length of string
xor cx,cx
or cl,[bx] ;Get length of string
inc bx ;Point to string.
clc
entry_box_1:
mov ctlc_stack,0
mov ctlc_return,0
ret
entry_box_error:
mov byte ptr [bx+1],0
xor cx,cx
inc bx
stc
jmp entry_box_1
entry_box endp
;--------------------------------------------------------------------
; SCAN4TERM - Checks to see if a character is a filename terminator.
; Entry: AL - character
; Exit: ZF - Set if terminator.
;--------------------------------------------------------------------
term_chars db ".:;,=+/",22h,"[]|<> ",9,13,0 ;Filename term. chars
term_chars_end = $
scan4term proc near
push cx
push di
mov cx,offset term_chars_end - offset term_chars
mov di,offset term_chars
repne scasb ;See if char is a terminator
pop di
pop cx
ret
scan4term endp
;--------------------------------------------------------------------
; CAPS CHAR - capitalizes a character
; Entry: AL - character
;--------------------------------------------------------------------
caps_char proc near
cmp al,"a"
jb caps1
cmp al,"z"
ja caps1
and al,0dfh
caps1:
ret
caps_char endp
;--------------------------------------------------------------------
; ASCIIZ2FN - Converts a filename in ASCIIZ format to 8.3 format
; Entry: SI - Pointer to filename
; DI - Pointer to buffer to store the 8.3 string.
; Exit: SI - Pointer to 8.3 name.
;--------------------------------------------------------------------
asciiz2fn proc near
push bx
push di
push di
push di
mov cx,11 ;Fill destination buffer
mov al," " ; with blanks.
rep stosb
pop di
mov bx,di ;Save ptr to buffer
mov cx,8
add bx,cx ;BX = ptr to ext
asciiz2fn_1:
lodsb ;Read each character in the
cmp al,"." ; name. If '.' then jmp
je asciiz2fn_ext ; to code for ext. If term
call scan4term ; char, end filename, else
je asciiz2fn_exit ; write the char in the dest
call caps_char ; buffer.
stosb
loop asciiz2fn_1
asciiz2fn_3:
lodsb ;If > 8 characters, scan until
cmp al,"." ; '.' or end of string.
je asciiz2fn_ext
call scan4term
je asciiz2fn_exit
jmp short asciiz2fn_3
asciiz2fn_ext:
mov di,bx ;Get ptr to ext
mov cx,3
asciiz2fn_4:
lodsb ;Save the ext just like the
call scan4term ; filename.
je asciiz2fn_exit
call caps_char
stosb
loop asciiz2fn_4
asciiz2fn_exit:
pop si
pop di
pop bx
ret
asciiz2fn endp
;--------------------------------------------------------------------
; FN2ASCIIZ - Converts a filename in 8.3 format to ASCIIZ
; Entry: SI - Pointer to filename
; DI - Pointer to buffer to store the ASCIIZ string.
; Exit: SI - Pointer to ASCIIZ name.
; CX - Length of string
;--------------------------------------------------------------------
fn2asciiz proc near
push bx
push dx
push di ;Save ptr to destination
mov bx,si
mov cx,8
xor dx,dx ;Clear count
fn2asciiz_1:
lodsb
cmp al," " ;See if space
je fn2asciiz_2 ;If so, end of filename
jb fn2asciiz_4 ;If ctl char, no ext.
stosb
inc dx
loop fn2asciiz_1
fn2asciiz_2:
mov si,bx ;Compute ptr to ext.
add si,8
mov al,"."
stosb
inc dx
mov cx,3
fn2asciiz_3:
lodsb
cmp al," " ;See if space
jbe fn2asciiz_4 ;If so, end of ext
stosb
inc dx
loop fn2asciiz_3
fn2asciiz_4:
xor al,al ;Terminate string with zero
stosb
mov cx,dx ;Copy count
pop si ;Get ptr to filename start
pop dx
pop bx
ret
fn2asciiz endp
;--------------------------------------------------------------------
; PRINT FILENAME - Prints a filename
; Entry: SI - Pointer to filename in 8.3 format
; DH - Row to start display
;--------------------------------------------------------------------
print_fn proc near
mov di,offset key_buffer
call fn2asciiz
call write_line_at ;Write string
ret
print_fn endp
;-----------------------------------------------------------------------------
; WRITE ERROR - Writes an error message to the screen.
; Entry: SI - Ptr to error ASCIIZ message string.
;-----------------------------------------------------------------------------
write_error proc near
mov dx,error_msg_loc ;Get location for error
call clear_line ; message.
call write_line_at
ret
write_error endp
;-----------------------------------------------------------------------------
; CLEAR LINE - Clears a line off the screen.
; Entry: DH - Line to clear
;-----------------------------------------------------------------------------
clear_line proc near
push dx
mov cx,dx ;Copy cursor start loc
mov dl,80 ;Scroll 1 line to end
mov cl,0
call scroll_block
pop dx
ret
clear_line endp
;-----------------------------------------------------------------------------
; CLEAR MSG - Clears a message off the screen.
; Entry: DH - Line to clear
;-----------------------------------------------------------------------------
clear_msg proc near
mov cx,0800h ;Row 8 Col 0
mov dx,0a50h ;Row 10 Col 80
call scroll_block
ret
clear_msg endp
end_of_code = $
code ends
end entry
cmp al,"a"
jb caps1
cmp al,"z"
ja caps1